Merge from TIZEN 2.3
[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 # ifdef _F_USE_DLOG_
26 #  include "dlog.h"
27 #  undef LOG_TAG
28 #  define LOG_TAG "E17"
29 # endif
30
31 /* These are compatible with netwm */
32 #define RESIZE_TL   0
33 #define RESIZE_T    1
34 #define RESIZE_TR   2
35 #define RESIZE_R    3
36 #define RESIZE_BR   4
37 #define RESIZE_B    5
38 #define RESIZE_BL   6
39 #define RESIZE_L    7
40 #define MOVE        8
41 #define RESIZE_NONE 11
42
43 /* local subsystem functions */
44 static void _e_border_pri_raise(E_Border *bd);
45 static void _e_border_pri_norm(E_Border *bd);
46 static void _e_border_free(E_Border *bd);
47 static void _e_border_del(E_Border *bd);
48
49 #ifdef PRINT_LOTS_OF_DEBUG
50 #define E_PRINT_BORDER_INFO(X) \
51   _e_border_print(X, __PRETTY_FUNC__)
52
53 static void _e_border_print(E_Border   *bd,
54                             const char *func);
55 #endif
56
57 /* FIXME: these likely belong in a separate icccm/client handler */
58 /* and the border needs to become a dumb object that just does what its */
59 /* told to do */
60 static Eina_Bool _e_border_cb_window_show_request(void *data,
61                                                   int   ev_type,
62                                                   void *ev);
63 static Eina_Bool _e_border_cb_window_destroy(void *data,
64                                              int   ev_type,
65                                              void *ev);
66 static Eina_Bool _e_border_cb_window_hide(void *data,
67                                           int   ev_type,
68                                           void *ev);
69 static Eina_Bool _e_border_cb_window_reparent(void *data,
70                                               int   ev_type,
71                                               void *ev);
72 static Eina_Bool _e_border_cb_window_configure_request(void *data,
73                                                        int   ev_type,
74                                                        void *ev);
75 static Eina_Bool _e_border_cb_window_resize_request(void *data,
76                                                     int   ev_type,
77                                                     void *ev);
78 static Eina_Bool _e_border_cb_window_gravity(void *data,
79                                              int   ev_type,
80                                              void *ev);
81 static Eina_Bool _e_border_cb_window_stack_request(void *data,
82                                                    int   ev_type,
83                                                    void *ev);
84 static Eina_Bool _e_border_cb_window_property(void *data,
85                                               int   ev_type,
86                                               void *ev);
87 static Eina_Bool _e_border_cb_window_colormap(void *data,
88                                               int   ev_type,
89                                               void *ev);
90 static Eina_Bool _e_border_cb_window_shape(void *data,
91                                            int   ev_type,
92                                            void *ev);
93 static Eina_Bool _e_border_cb_window_focus_in(void *data,
94                                               int   ev_type,
95                                               void *ev);
96 static Eina_Bool _e_border_cb_window_focus_out(void *data,
97                                                int   ev_type,
98                                                void *ev);
99 static Eina_Bool _e_border_cb_client_message(void *data,
100                                              int   ev_type,
101                                              void *ev);
102
103 static Eina_Bool _e_border_cb_window_state_request(void *data,
104                                                    int   ev_type,
105                                                    void *ev);
106 static Eina_Bool _e_border_cb_window_move_resize_request(void *data,
107                                                          int   ev_type,
108                                                          void *ev);
109 static Eina_Bool _e_border_cb_desktop_change(void *data,
110                                              int   ev_type,
111                                              void *ev);
112 static Eina_Bool _e_border_cb_sync_alarm(void *data,
113                                          int   ev_type,
114                                          void *ev);
115 static Eina_Bool _e_border_cb_efreet_cache_update(void *data,
116                                                   int   ev_type,
117                                                   void *ev);
118 static Eina_Bool _e_border_cb_config_icon_theme(void *data,
119                                                 int   ev_type,
120                                                 void *ev);
121
122 static Eina_Bool _e_border_cb_pointer_warp(void *data,
123                                            int   ev_type,
124                                            void *ev);
125 static void _e_border_cb_signal_bind(void        *data,
126                                      Evas_Object *obj,
127                                      const char  *emission,
128                                      const char  *source);
129 static Eina_Bool _e_border_cb_mouse_in(void *data,
130                                        int   type,
131                                        void *event);
132 static Eina_Bool _e_border_cb_mouse_out(void *data,
133                                         int   type,
134                                         void *event);
135 static Eina_Bool _e_border_cb_mouse_wheel(void *data,
136                                           int   type,
137                                           void *event);
138 static Eina_Bool _e_border_cb_mouse_down(void *data,
139                                          int   type,
140                                          void *event);
141 static Eina_Bool _e_border_cb_mouse_up(void *data,
142                                        int   type,
143                                        void *event);
144 static Eina_Bool _e_border_cb_mouse_move(void *data,
145                                          int   type,
146                                          void *event);
147 static Eina_Bool _e_border_cb_grab_replay(void *data,
148                                           int   type,
149                                           void *event);
150 static void _e_border_cb_drag_finished(E_Drag *drag,
151                                        int     dropped);
152 #ifdef _F_USE_DESK_WINDOW_PROFILE_
153 static Eina_Bool _e_border_cb_desk_window_profile_change(void *data,
154                                                          int   ev_type,
155                                                          void *ev);
156 #endif
157 #ifdef _F_ZONE_WINDOW_ROTATION_
158 static Eina_Bool _e_border_cb_zone_rotation_change_begin(void *data,
159                                                          int   ev_type,
160                                                          void *ev);
161 static void _e_border_cb_rotation_sync_job(void *data);
162 static void _e_border_cb_rotation_async_job(void *data);
163 static Eina_Bool _e_border_rotation_change_prepare_timeout(void *data);
164 static void      _e_border_rotation_change_request(E_Zone *zone);
165 static void      _e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush);
166 static Eina_Bool _e_border_rotation_change_done_timeout(void *data);
167 static void      _e_border_rotation_change_done(void);
168 static Eina_Bool _e_border_rotation_geom_get(E_Border  *bd,
169                                              E_Zone    *zone,
170                                              int        ang,
171                                              int       *x,
172                                              int       *y,
173                                              int       *w,
174                                              int       *h,
175                                              Eina_Bool *move);
176 static void      _e_border_rotation_list_remove(E_Border *bd);
177 static Eina_Bool _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h);
178 static int       _e_border_rotation_angle_get(E_Border *bd);
179 static Eina_Bool _e_border_rotation_zone_set(E_Zone *zone);
180 static Eina_Bool _e_border_rotatable_check(E_Border *bd, int ang);
181 static Eina_Bool _e_border_is_vkbd(E_Border *bd);
182 static Eina_Bool _e_border_cb_window_configure(void *data,
183                                                int   ev_type,
184                                                void *ev);
185 static Eina_Bool _e_border_vkbd_show_prepare_timeout(void *data);
186 static Eina_Bool _e_border_vkbd_hide_prepare_timeout(void *data);
187 static void      _e_border_vkbd_show(E_Border *bd);
188 static void      _e_border_vkbd_hide(E_Border *bd);
189 static Eina_Bool _e_border_rotation_set_internal(E_Border *bd, int rotation, Eina_Bool *pending);
190 #endif
191 static void      _e_border_move_resize_internal(E_Border *bd,
192                                                 int       x,
193                                                 int       y,
194                                                 int       w,
195                                                 int       h,
196                                                 Eina_Bool without_border,
197                                                 Eina_Bool move);
198
199 static void      _e_border_eval(E_Border *bd);
200 static void      _e_border_eval0(E_Border *bd);
201 static void      _e_border_container_layout_hook(E_Container *con);
202
203 static void      _e_border_moveinfo_gather(E_Border   *bd,
204                                            const char *source);
205 static void      _e_border_resize_handle(E_Border *bd);
206
207 static Eina_Bool _e_border_shade_animator(void *data);
208
209 static void      _e_border_event_border_add_free(void *data,
210                                                  void *ev);
211 static void      _e_border_event_border_remove_free(void *data,
212                                                     void *ev);
213 static void      _e_border_event_border_zone_set_free(void *data,
214                                                       void *ev);
215 static void      _e_border_event_border_desk_set_free(void *data,
216                                                       void *ev);
217 static void      _e_border_event_border_stack_free(void *data,
218                                                    void *ev);
219 static void      _e_border_event_border_icon_change_free(void *data,
220                                                          void *ev);
221 static void      _e_border_event_border_urgent_change_free(void *data,
222                                                            void *ev);
223 static void      _e_border_event_border_focus_in_free(void *data,
224                                                       void *ev);
225 static void      _e_border_event_border_focus_out_free(void *data,
226                                                        void *ev);
227 static void      _e_border_event_border_resize_free(void *data,
228                                                     void *ev);
229 static void      _e_border_event_border_move_free(void *data,
230                                                   void *ev);
231 static void      _e_border_event_border_show_free(void *data,
232                                                   void *ev);
233 static void      _e_border_event_border_hide_free(void *data,
234                                                   void *ev);
235 static void      _e_border_event_border_iconify_free(void *data,
236                                                      void *ev);
237 static void      _e_border_event_border_uniconify_free(void *data,
238                                                        void *ev);
239 static void      _e_border_event_border_stick_free(void *data,
240                                                    void *ev);
241 static void      _e_border_event_border_unstick_free(void *data,
242                                                      void *ev);
243 static void      _e_border_event_border_property_free(void *data,
244                                                       void *ev);
245 static void      _e_border_event_border_fullscreen_free(void *data,
246                                                         void *ev);
247 static void      _e_border_event_border_unfullscreen_free(void *data,
248                                                           void *ev);
249 #ifdef _F_ZONE_WINDOW_ROTATION_
250 static void      _e_border_event_border_rotation_change_begin_free(void *data,
251                                                                    void *ev);
252 static void      _e_border_event_border_rotation_change_cancel_free(void *data,
253                                                                     void *ev);
254 static void      _e_border_event_border_rotation_change_end_free(void *data,
255                                                                  void *ev);
256 static void      _e_border_event_border_rotation_change_begin_send(E_Border *bd);
257 #endif
258
259 static void      _e_border_zone_update(E_Border *bd);
260
261 static int       _e_border_resize_begin(E_Border *bd);
262 static int       _e_border_resize_end(E_Border *bd);
263 static void      _e_border_resize_update(E_Border *bd);
264
265 static int       _e_border_move_begin(E_Border *bd);
266 static int       _e_border_move_end(E_Border *bd);
267 static void      _e_border_move_update(E_Border *bd);
268
269 static Eina_Bool _e_border_cb_ping_poller(void *data);
270 static Eina_Bool _e_border_cb_kill_timer(void *data);
271
272 static void      _e_border_pointer_resize_begin(E_Border *bd);
273 static void      _e_border_pointer_resize_end(E_Border *bd);
274 static void      _e_border_pointer_move_begin(E_Border *bd);
275 static void      _e_border_pointer_move_end(E_Border *bd);
276
277 static void      _e_border_hook_call(E_Border_Hook_Point hookpoint,
278                                      void               *bd);
279
280 static void _e_border_client_move_resize_send(E_Border *bd);
281
282 static void _e_border_frame_replace(E_Border *bd,
283             Eina_Bool argb);
284
285 static void _e_border_shape_input_rectangle_set(E_Border* bd);
286 static void _e_border_show(E_Border *bd);
287 static void _e_border_hide(E_Border *bd);
288
289
290 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
291 static void _e_border_latest_stacked_focus (E_Border* bd);
292 static void _e_border_check_stack (E_Border *bd);
293 static void _e_border_focus_top_stack_set (E_Border* bd);
294 #endif
295 #if _F_BORDER_CLIP_TO_ZONE_
296 static void      _e_border_shape_input_clip_to_zone(E_Border *bd);
297 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
298
299 #ifdef _F_DEICONIFY_APPROVE_
300 static void _e_border_msg_handler(void       *data,
301                                   const char *name,
302                                   const char *info,
303                                   int         val,
304                                   E_Object   *obj,
305                                   void       *msgdata);
306 #endif
307
308 /* local subsystem globals */
309 static Eina_List *handlers = NULL;
310 static Eina_List *borders = NULL;
311 static Eina_Hash *borders_hash = NULL;
312 static E_Border *focused = NULL;
313 static E_Border *focusing = NULL;
314 static Eina_List *focus_next = NULL;
315 static Ecore_X_Time focus_time = 0;
316
317 static E_Border *bdresize = NULL;
318 static E_Border *bdmove = NULL;
319 static E_Drag *drag_border = NULL;
320
321 static int grabbed = 0;
322
323 static Eina_List *focus_stack = NULL;
324 static Eina_List *raise_stack = NULL;
325
326 static Ecore_X_Randr_Screen_Size screen_size = { -1, -1 };
327 static int screen_size_index = -1;
328
329 static int focus_track_frozen = 0;
330
331 static int warp_to = 0;
332 static int warp_to_x = 0;
333 static int warp_to_y = 0;
334 static int warp_x = 0;
335 static int warp_y = 0;
336 static Ecore_X_Window warp_to_win;
337 static Ecore_Timer *warp_timer = NULL;
338
339 #ifdef _F_DEICONIFY_APPROVE_
340 static E_Msg_Handler *_msg_handler = NULL;
341 #endif
342
343 #ifdef _F_ZONE_WINDOW_ROTATION_
344 typedef struct _E_Border_Rotation      E_Border_Rotation;
345 typedef struct _E_Border_Rotation_Info E_Border_Rotation_Info;
346
347 struct _E_Border_Rotation
348 {
349    Eina_List     *list;
350    Eina_List     *async_list;
351
352    Eina_Bool      wait_prepare_done;
353    Ecore_Timer   *prepare_timer;
354    Ecore_Timer   *done_timer;
355    Ecore_Job     *sync_job;
356    Ecore_Job     *async_job;
357
358    Ecore_X_Window vkbd_ctrl_win;
359    E_Border      *vkbd;
360    E_Border      *vkbd_prediction;
361
362    /* vkbd show/hide preprare */
363    Eina_Bool      vkbd_show_prepare_done;
364    Ecore_Timer   *vkbd_show_prepare_timer;
365    Ecore_Timer   *vkbd_show_timer;
366
367    Eina_Bool      vkbd_hide_prepare_done;
368    Ecore_Timer   *vkbd_hide_prepare_timer;
369    Ecore_Timer   *vkbd_hide_timer;
370
371    Eina_Bool      fetch;
372    Eina_List     *msgs;
373 };
374
375 struct _E_Border_Rotation_Info
376 {
377    int            x, y, w, h;
378    int            ang;
379    E_Border      *bd;
380    Eina_Bool      win_resize;
381 };
382
383 static E_Border_Rotation rot =
384 {
385    NULL,
386    NULL,
387    EINA_FALSE,
388    NULL,
389    NULL,
390    NULL,
391    NULL,
392    0,
393    NULL,
394    NULL,
395    EINA_FALSE,
396    NULL,
397    NULL,
398    EINA_FALSE,
399    NULL,
400    NULL,
401    EINA_FALSE,
402    NULL
403 };
404 #endif
405
406 EAPI int E_EVENT_BORDER_ADD = 0;
407 EAPI int E_EVENT_BORDER_REMOVE = 0;
408 EAPI int E_EVENT_BORDER_ZONE_SET = 0;
409 EAPI int E_EVENT_BORDER_DESK_SET = 0;
410 EAPI int E_EVENT_BORDER_RESIZE = 0;
411 EAPI int E_EVENT_BORDER_MOVE = 0;
412 EAPI int E_EVENT_BORDER_SHOW = 0;
413 EAPI int E_EVENT_BORDER_HIDE = 0;
414 EAPI int E_EVENT_BORDER_ICONIFY = 0;
415 EAPI int E_EVENT_BORDER_UNICONIFY = 0;
416 EAPI int E_EVENT_BORDER_STICK = 0;
417 EAPI int E_EVENT_BORDER_UNSTICK = 0;
418 EAPI int E_EVENT_BORDER_STACK = 0;
419 EAPI int E_EVENT_BORDER_ICON_CHANGE = 0;
420 EAPI int E_EVENT_BORDER_URGENT_CHANGE = 0;
421 EAPI int E_EVENT_BORDER_FOCUS_IN = 0;
422 EAPI int E_EVENT_BORDER_FOCUS_OUT = 0;
423 EAPI int E_EVENT_BORDER_PROPERTY = 0;
424 EAPI int E_EVENT_BORDER_FULLSCREEN = 0;
425 EAPI int E_EVENT_BORDER_UNFULLSCREEN = 0;
426 #ifdef _F_ZONE_WINDOW_ROTATION_
427 EAPI int E_EVENT_BORDER_ROTATION = 0; /* deprecated */
428 EAPI int E_EVENT_BORDER_ROTATION_CHANGE_BEGIN = 0;
429 EAPI int E_EVENT_BORDER_ROTATION_CHANGE_CANCEL = 0;
430 EAPI int E_EVENT_BORDER_ROTATION_CHANGE_END = 0;
431 #endif
432
433 #define GRAV_SET(bd, grav)                                \
434   ecore_x_window_gravity_set(bd->bg_win, grav);           \
435   ecore_x_window_gravity_set(bd->client.shell_win, grav); \
436   ecore_x_window_gravity_set(bd->client.win, grav);
437
438 static Eina_List *
439 _e_border_sub_borders_new(E_Border *bd)
440 {
441    Eina_List *list = NULL, *l;
442    E_Border *child;
443    E_Border_List *bl;
444
445    EINA_LIST_FOREACH(bd->transients, l, child)
446      {
447         if (!eina_list_data_find(list, child))
448           list = eina_list_append(list, child);
449      }
450    bl = e_container_border_list_first(bd->zone->container);
451    while ((child = e_container_border_list_next(bl)))
452      {
453         if (e_object_is_del(E_OBJECT(child))) continue;
454         if (child == bd) continue;
455 /*
456         if ((bd->client.icccm.client_leader) &&
457             (child->client.icccm.client_leader ==
458                 bd->client.icccm.client_leader))
459           {
460              printf("bd %s in group with %s\n",
461                     e_border_name_get(child),
462                     e_border_name_get(bd));
463              if (!eina_list_data_find(list, child))
464                list = eina_list_append(list, child);
465           }
466  */
467      }
468    e_container_border_list_free(bl);
469    return list;
470 }
471
472 /* externally accessible functions */
473 EINTERN int
474 e_border_init(void)
475 {
476    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, _e_border_cb_window_show_request, NULL));
477    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _e_border_cb_window_destroy, NULL));
478    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, _e_border_cb_window_hide, NULL));
479    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_REPARENT, _e_border_cb_window_reparent, NULL));
480    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, _e_border_cb_window_configure_request, NULL));
481    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, _e_border_cb_window_resize_request, NULL));
482    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_GRAVITY, _e_border_cb_window_gravity, NULL));
483    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, _e_border_cb_window_stack_request, NULL));
484    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _e_border_cb_window_property, NULL));
485    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_COLORMAP, _e_border_cb_window_colormap, NULL));
486    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHAPE, _e_border_cb_window_shape, NULL));
487    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, _e_border_cb_window_focus_in, NULL));
488    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _e_border_cb_window_focus_out, NULL));
489    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _e_border_cb_client_message, NULL));
490    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, _e_border_cb_window_state_request, NULL));
491    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, _e_border_cb_window_move_resize_request, NULL));
492    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_DESKTOP_CHANGE, _e_border_cb_desktop_change, NULL));
493    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_SYNC_ALARM, _e_border_cb_sync_alarm, NULL));
494 #ifdef _F_ZONE_WINDOW_ROTATION_
495    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, _e_border_cb_window_configure, NULL));
496 #endif
497
498    ecore_x_passive_grab_replay_func_set(_e_border_cb_grab_replay, NULL);
499
500    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_POINTER_WARP, _e_border_cb_pointer_warp, NULL));
501    handlers = eina_list_append(handlers, ecore_event_handler_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE, _e_border_cb_efreet_cache_update, NULL));
502    handlers = eina_list_append(handlers, ecore_event_handler_add(EFREET_EVENT_ICON_CACHE_UPDATE, _e_border_cb_efreet_cache_update, NULL));
503    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_CONFIG_ICON_THEME, _e_border_cb_config_icon_theme, NULL));
504 #ifdef _F_USE_DESK_WINDOW_PROFILE_
505    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_DESK_WINDOW_PROFILE_CHANGE, _e_border_cb_desk_window_profile_change, NULL));
506 #endif
507 #ifdef _F_ZONE_WINDOW_ROTATION_
508    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, _e_border_cb_zone_rotation_change_begin, NULL));
509 #endif
510
511 #ifdef _F_DEICONIFY_APPROVE_
512    _msg_handler = e_msg_handler_add(_e_border_msg_handler, NULL);
513 #endif
514
515    if (!borders_hash) borders_hash = eina_hash_string_superfast_new(NULL);
516
517    E_EVENT_BORDER_ADD = ecore_event_type_new();
518    E_EVENT_BORDER_REMOVE = ecore_event_type_new();
519    E_EVENT_BORDER_DESK_SET = ecore_event_type_new();
520    E_EVENT_BORDER_ZONE_SET = ecore_event_type_new();
521    E_EVENT_BORDER_RESIZE = ecore_event_type_new();
522    E_EVENT_BORDER_MOVE = ecore_event_type_new();
523    E_EVENT_BORDER_SHOW = ecore_event_type_new();
524    E_EVENT_BORDER_HIDE = ecore_event_type_new();
525    E_EVENT_BORDER_ICONIFY = ecore_event_type_new();
526    E_EVENT_BORDER_UNICONIFY = ecore_event_type_new();
527    E_EVENT_BORDER_STICK = ecore_event_type_new();
528    E_EVENT_BORDER_UNSTICK = ecore_event_type_new();
529    E_EVENT_BORDER_STACK = ecore_event_type_new();
530    E_EVENT_BORDER_ICON_CHANGE = ecore_event_type_new();
531    E_EVENT_BORDER_URGENT_CHANGE = ecore_event_type_new();
532    E_EVENT_BORDER_FOCUS_IN = ecore_event_type_new();
533    E_EVENT_BORDER_FOCUS_OUT = ecore_event_type_new();
534    E_EVENT_BORDER_PROPERTY = ecore_event_type_new();
535    E_EVENT_BORDER_FULLSCREEN = ecore_event_type_new();
536    E_EVENT_BORDER_UNFULLSCREEN = ecore_event_type_new();
537 #ifdef _F_ZONE_WINDOW_ROTATION_
538    E_EVENT_BORDER_ROTATION = ecore_event_type_new(); /* deprecated */
539    E_EVENT_BORDER_ROTATION_CHANGE_BEGIN = ecore_event_type_new();
540    E_EVENT_BORDER_ROTATION_CHANGE_CANCEL = ecore_event_type_new();
541    E_EVENT_BORDER_ROTATION_CHANGE_END = ecore_event_type_new();
542 #endif
543
544 //   e_init_undone();
545
546    return 1;
547 }
548
549 EINTERN int
550 e_border_shutdown(void)
551 {
552    E_FREE_LIST(handlers, ecore_event_handler_del);
553
554    if (borders_hash) eina_hash_free(borders_hash);
555    borders_hash = NULL;
556    e_int_border_menu_hooks_clear();
557
558    return 1;
559 }
560
561 EAPI E_Border *
562 e_border_new(E_Container   *con,
563              Ecore_X_Window win,
564              int            first_map,
565              int            internal)
566 {
567    E_Border *bd, *bd2;
568    Ecore_X_Window_Attributes *att;
569    unsigned int managed, desk[2];
570    int deskx, desky;
571
572    bd = E_OBJECT_ALLOC(E_Border, E_BORDER_TYPE, _e_border_free);
573    if (!bd) return NULL;
574    ecore_x_window_shadow_tree_flush();
575    e_object_del_func_set(E_OBJECT(bd), E_OBJECT_CLEANUP_FUNC(_e_border_del));
576
577    bd->w = 1;
578    bd->h = 1;
579    /* FIXME: ewww - round trip */
580    bd->client.argb = ecore_x_window_argb_get(win);
581    if (bd->client.argb)
582      bd->win = ecore_x_window_manager_argb_new(con->win, 0, 0, bd->w, bd->h);
583    else
584      {
585         bd->win = ecore_x_window_override_new(con->win, 0, 0, bd->w, bd->h);
586         ecore_x_window_shape_events_select(bd->win, 1);
587      }
588    e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
589    e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
590    e_focus_setup(bd);
591    bd->bg_ecore_evas = e_canvas_new(bd->win,
592                                     0, 0, bd->w, bd->h, 1, 0,
593                                     &(bd->bg_win));
594    ecore_evas_ignore_events_set(bd->bg_ecore_evas, EINA_TRUE);
595    e_canvas_add(bd->bg_ecore_evas);
596    bd->event_win = ecore_x_window_input_new(bd->win, 0, 0, bd->w, bd->h);
597    bd->bg_evas = ecore_evas_get(bd->bg_ecore_evas);
598    ecore_x_window_shape_events_select(bd->bg_win, 1);
599    ecore_evas_name_class_set(bd->bg_ecore_evas, "E", "Frame_Window");
600    ecore_evas_title_set(bd->bg_ecore_evas, "Enlightenment Frame");
601    if (bd->client.argb)
602      bd->client.shell_win = ecore_x_window_manager_argb_new(bd->win, 0, 0, 1, 1);
603    else
604      bd->client.shell_win = ecore_x_window_override_new(bd->win, 0, 0, 1, 1);
605    ecore_x_window_container_manage(bd->client.shell_win);
606    if (!internal) ecore_x_window_client_manage(win);
607    /* FIXME: Round trip. XCB */
608    /* fetch needed to avoid grabbing the server as window may vanish */
609    att = &bd->client.initial_attributes;
610    if ((!ecore_x_window_attributes_get(win, att)) || (att->input_only))
611      {
612         //      printf("##- ATTR FETCH FAILED/INPUT ONLY FOR 0x%x - ABORT MANAGE\n", win);
613           e_canvas_del(bd->bg_ecore_evas);
614           ecore_evas_free(bd->bg_ecore_evas);
615           ecore_x_window_free(bd->client.shell_win);
616           e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
617           e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
618           ecore_x_window_free(bd->win);
619           free(bd);
620           return NULL;
621      }
622
623    /* printf("##- ON MAP CLIENT 0x%x SIZE %ix%i %i:%i\n",
624     *     bd->client.win, bd->client.w, bd->client.h, att->x, att->y); */
625
626    /* FIXME: if first_map is 1 then we should ignore the first hide event
627     * or ensure the window is already hidden and events flushed before we
628     * create a border for it */
629    if (first_map)
630      {
631         // printf("##- FIRST MAP\n");
632           bd->x = att->x;
633           bd->y = att->y;
634           bd->changes.pos = 1;
635           bd->re_manage = 1;
636           // needed to be 1 for internal windw and on restart.
637           // bd->ignore_first_unmap = 2;
638      }
639
640    bd->client.win = win;
641    bd->zone = e_zone_current_get(con);
642
643    _e_border_hook_call(E_BORDER_HOOK_NEW_BORDER, bd);
644
645    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN, _e_border_cb_mouse_in, bd));
646    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT, _e_border_cb_mouse_out, bd));
647    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_cb_mouse_down, bd));
648    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, _e_border_cb_mouse_up, bd));
649    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, _e_border_cb_mouse_move, bd));
650    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL, _e_border_cb_mouse_wheel, bd));
651
652    bd->client.icccm.title = NULL;
653    bd->client.icccm.name = NULL;
654    bd->client.icccm.class = NULL;
655    bd->client.icccm.icon_name = NULL;
656    bd->client.icccm.machine = NULL;
657    bd->client.icccm.min_w = 1;
658    bd->client.icccm.min_h = 1;
659    bd->client.icccm.max_w = 32767;
660    bd->client.icccm.max_h = 32767;
661    bd->client.icccm.base_w = 0;
662    bd->client.icccm.base_h = 0;
663    bd->client.icccm.step_w = -1;
664    bd->client.icccm.step_h = -1;
665    bd->client.icccm.min_aspect = 0.0;
666    bd->client.icccm.max_aspect = 0.0;
667    bd->client.icccm.accepts_focus = 1;
668
669    bd->client.netwm.pid = 0;
670    bd->client.netwm.name = NULL;
671    bd->client.netwm.icon_name = NULL;
672    bd->client.netwm.desktop = 0;
673    bd->client.netwm.state.modal = 0;
674    bd->client.netwm.state.sticky = 0;
675    bd->client.netwm.state.shaded = 0;
676    bd->client.netwm.state.hidden = 0;
677    bd->client.netwm.state.maximized_v = 0;
678    bd->client.netwm.state.maximized_h = 0;
679    bd->client.netwm.state.skip_taskbar = 0;
680    bd->client.netwm.state.skip_pager = 0;
681    bd->client.netwm.state.fullscreen = 0;
682    bd->client.netwm.state.stacking = E_STACKING_NONE;
683    bd->client.netwm.action.move = 0;
684    bd->client.netwm.action.resize = 0;
685    bd->client.netwm.action.minimize = 0;
686    bd->client.netwm.action.shade = 0;
687    bd->client.netwm.action.stick = 0;
688    bd->client.netwm.action.maximized_h = 0;
689    bd->client.netwm.action.maximized_v = 0;
690    bd->client.netwm.action.fullscreen = 0;
691    bd->client.netwm.action.change_desktop = 0;
692    bd->client.netwm.action.close = 0;
693    bd->client.netwm.type = ECORE_X_WINDOW_TYPE_UNKNOWN;
694
695    {
696       int at_num = 0, i;
697       Ecore_X_Atom *atoms;
698
699       atoms = ecore_x_window_prop_list(bd->client.win, &at_num);
700       bd->client.icccm.fetch.command = 1;
701       if (atoms)
702         {
703            Eina_Bool video_parent = EINA_FALSE;
704            Eina_Bool video_position = EINA_FALSE;
705
706            /* icccm */
707             for (i = 0; i < at_num; i++)
708               {
709                  if (atoms[i] == ECORE_X_ATOM_WM_NAME)
710                    bd->client.icccm.fetch.title = 1;
711                  else if (atoms[i] == ECORE_X_ATOM_WM_CLASS)
712                    bd->client.icccm.fetch.name_class = 1;
713                  else if (atoms[i] == ECORE_X_ATOM_WM_ICON_NAME)
714                    bd->client.icccm.fetch.icon_name = 1;
715                  else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_MACHINE)
716                    bd->client.icccm.fetch.machine = 1;
717                  else if (atoms[i] == ECORE_X_ATOM_WM_HINTS)
718                    bd->client.icccm.fetch.hints = 1;
719                  else if (atoms[i] == ECORE_X_ATOM_WM_NORMAL_HINTS)
720                    bd->client.icccm.fetch.size_pos_hints = 1;
721                  else if (atoms[i] == ECORE_X_ATOM_WM_PROTOCOLS)
722                    bd->client.icccm.fetch.protocol = 1;
723                  else if (atoms[i] == ECORE_X_ATOM_MOTIF_WM_HINTS)
724                    bd->client.mwm.fetch.hints = 1;
725                  else if (atoms[i] == ECORE_X_ATOM_WM_TRANSIENT_FOR)
726                    {
727                       bd->client.icccm.fetch.transient_for = 1;
728                       bd->client.netwm.fetch.type = 1;
729                    }
730                  else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_LEADER)
731                    bd->client.icccm.fetch.client_leader = 1;
732                  else if (atoms[i] == ECORE_X_ATOM_WM_WINDOW_ROLE)
733                    bd->client.icccm.fetch.window_role = 1;
734                  else if (atoms[i] == ECORE_X_ATOM_WM_STATE)
735                    bd->client.icccm.fetch.state = 1;
736               }
737             /* netwm, loop again, netwm will ignore some icccm, so we
738              * have to be sure that netwm is checked after */
739             for (i = 0; i < at_num; i++)
740               {
741                  if (atoms[i] == ECORE_X_ATOM_NET_WM_NAME)
742                    {
743      /* Ignore icccm */
744                        bd->client.icccm.fetch.title = 0;
745                        bd->client.netwm.fetch.name = 1;
746                    }
747                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON_NAME)
748                    {
749      /* Ignore icccm */
750                        bd->client.icccm.fetch.icon_name = 0;
751                        bd->client.netwm.fetch.icon_name = 1;
752                    }
753                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON)
754                    {
755                       bd->client.netwm.fetch.icon = 1;
756                    }
757                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_USER_TIME)
758                    {
759                       bd->client.netwm.fetch.user_time = 1;
760                    }
761                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT)
762                    {
763                       DBG("ECORE_X_ATOM_NET_WM_STRUT");
764                       bd->client.netwm.fetch.strut = 1;
765                    }
766                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
767                    {
768                       DBG("ECORE_X_ATOM_NET_WM_STRUT_PARTIAL");
769                       bd->client.netwm.fetch.strut = 1;
770                    }
771                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_TYPE)
772                    {
773      /* Ignore mwm
774         bd->client.mwm.fetch.hints = 0;
775       */
776                         bd->client.netwm.fetch.type = 1;
777                    }
778                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STATE)
779                    {
780                       bd->client.netwm.fetch.state = 1;
781                    }
782               }
783             /* other misc atoms */
784             for (i = 0; i < at_num; i++)
785               {
786      /* loop to check for own atoms */
787                   if (atoms[i] == E_ATOM_WINDOW_STATE)
788                     {
789                        bd->client.e.fetch.state = 1;
790                     }
791      /* loop to check for qtopia atoms */
792                   if (atoms[i] == ATM__QTOPIA_SOFT_MENU)
793                     bd->client.qtopia.fetch.soft_menu = 1;
794                   else if (atoms[i] == ATM__QTOPIA_SOFT_MENUS)
795                     bd->client.qtopia.fetch.soft_menus = 1;
796      /* loop to check for vkbd atoms */
797                   else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
798                     bd->client.vkbd.fetch.state = 1;
799                   else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
800                     bd->client.vkbd.fetch.vkbd = 1;
801      /* loop to check for illume atoms */
802                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
803                     bd->client.illume.conformant.fetch.conformant = 1;
804                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
805                     bd->client.illume.quickpanel.fetch.state = 1;
806                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
807                     bd->client.illume.quickpanel.fetch.quickpanel = 1;
808                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
809                     bd->client.illume.quickpanel.fetch.priority.major = 1;
810                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
811                     bd->client.illume.quickpanel.fetch.priority.minor = 1;
812                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
813                     bd->client.illume.quickpanel.fetch.zone = 1;
814                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
815                     bd->client.illume.drag.fetch.locked = 1;
816                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG)
817                     bd->client.illume.drag.fetch.drag = 1;
818                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
819                     bd->client.illume.win_state.fetch.state = 1;
820                   else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_PARENT)
821                     video_parent = EINA_TRUE;
822                   else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_POSITION)
823                     video_position = EINA_TRUE;
824 #ifdef _F_USE_DESK_WINDOW_PROFILE_
825      /* loop to check for window profile list atom */
826                   else if (atoms[i] == ECORE_X_ATOM_E_PROFILE_LIST)
827                     bd->client.e.fetch.profile_list = 1;
828 #endif
829 #ifdef _F_ZONE_WINDOW_ROTATION_
830                   /* loop to check for wm rotation */
831                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED)
832                     {
833                        if (e_config->wm_win_rotation)
834                          bd->client.e.fetch.rot.support = 1;
835                     }
836                   else if ((atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) ||
837                            (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) ||
838                            (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) ||
839                            (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY))
840                     {
841                        if (e_config->wm_win_rotation)
842                          bd->client.e.fetch.rot.geom_hint = 1;
843                     }
844                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED)
845                     {
846                        if (e_config->wm_win_rotation)
847                          bd->client.e.fetch.rot.app_set = 1;
848                     }
849                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION)
850                     {
851                        if (e_config->wm_win_rotation)
852                          bd->client.e.fetch.rot.preferred_rot = 1;
853                     }
854                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)
855                     {
856                        if (e_config->wm_win_rotation)
857                          bd->client.e.fetch.rot.available_rots = 1;
858                     }
859 #endif
860 #ifdef _F_DEICONIFY_APPROVE_
861                   else if (atoms[i] == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
862                     {
863                        bd->client.e.state.deiconify_approve.support = 1;
864                     }
865 #endif
866               }
867             if (video_position && video_parent)
868               {
869                  bd->client.e.state.video = 1;
870                  bd->client.e.fetch.video_parent = 1;
871                  bd->client.e.fetch.video_position = 1;
872                  ecore_x_window_lower(bd->win);
873                  ecore_x_composite_window_events_disable(bd->win);
874                  ecore_x_window_ignore_set(bd->win, EINA_TRUE);
875                  fprintf(stderr, "We found a video window \\o/ %x\n", win);
876               }
877             free(atoms);
878         }
879    }
880    bd->client.border.changed = 1;
881
882    bd->client.w = att->w;
883    bd->client.h = att->h;
884
885 #ifdef _F_FIX_POSITION_PROBLEM_
886    bd->x = att->x;
887    bd->y = att->y;
888 #endif
889    bd->w = bd->client.w;
890    bd->h = bd->client.h;
891
892    bd->resize_mode = RESIZE_NONE;
893    bd->layer = 100;
894    bd->saved.layer = bd->layer;
895    bd->changes.icon = 1;
896    bd->changes.size = 1;
897    bd->changes.shape = 1;
898    bd->changes.shape_input = 1;
899
900    bd->offer_resistance = 1;
901
902    /* just to friggin make java happy - we're DELAYING the reparent until
903     * eval time...
904     */
905 /*   ecore_x_window_reparent(win, bd->client.shell_win, 0, 0); */
906    bd->need_reparent = 1;
907
908    ecore_x_window_border_width_set(win, 0);
909    ecore_x_window_show(bd->event_win);
910    ecore_x_window_show(bd->client.shell_win);
911    bd->shape = e_container_shape_add(con);
912
913    bd->take_focus = 1;
914    bd->new_client = 1;
915    bd->changed = 1;
916 #ifdef _F_ZONE_WINDOW_ROTATION_
917    bd->client.e.state.rot.preferred_rot = -1;
918    bd->client.e.state.rot.type = E_BORDER_ROTATION_TYPE_NORMAL;
919    bd->client.e.state.rot.changes = -1;
920    bd->client.e.state.rot.pending_show = 0;
921    bd->client.e.state.rot.curr = 0;
922    bd->client.e.state.rot.prev = 0;
923 #endif
924
925 //   bd->zone = e_zone_current_get(con);
926    bd->desk = e_desk_current_get(bd->zone);
927    e_container_border_add(bd);
928    borders = eina_list_append(borders, bd);
929    bd2 = eina_hash_find(borders_hash, e_util_winid_str_get(bd->client.win));
930    if (bd2)
931      {
932 #ifdef E_LOGGING
933         WRN("EEEEK! 2 borders with same client window id in them! very bad!\n"
934             "optimisations failing due to bizarre client behavior. will\n"
935             "work around.\n"
936             "bd=%p, bd->references=%i, bd->deleted=%i, bd->client.win=%x",
937                bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted,
938                bd2->client.win);
939
940         ELBF(ELBT_BD, 0, bd->client.win,
941              "ERR! 2 borders with same client win id in them! bd:%p ref:%i deleted:%i",
942              bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted);
943 #else
944         printf("EEEEK! 2 borders with same client window id in them! very bad!\n");
945         printf("optimisations failing due to bizarre client behavior. will\n");
946         printf("work around.\n");
947         printf("bd=%p, bd->references=%i, bd->deleted=%i, bd->client.win=%x\n",
948                bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted,
949                bd2->client.win);
950
951         ELBF(ELBT_BD, 0, bd->client.win,
952              "ERR! 2 borders with same client win id in them! bd:%p ref:%i deleted:%i",
953              bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted);
954 #endif
955
956 #ifdef _F_ZONE_WINDOW_ROTATION_
957         if ((rot.vkbd) && (rot.vkbd == bd2))
958           {
959              ELB(ELBT_BD, "UNSET VKBD", rot.vkbd->client.win);
960              ELBF(ELBT_BD, 1, rot.vkbd->client.win, "VKBD HIDE PREPARE_DONE:%d",
961                   rot.vkbd_hide_prepare_done);
962
963              if (rot.vkbd_hide_prepare_timer)
964                {
965                   ecore_timer_del(rot.vkbd_hide_prepare_timer);
966                   rot.vkbd_hide_prepare_timer = NULL;
967
968                   e_object_unref(E_OBJECT(bd2));
969                }
970
971              _e_border_vkbd_hide(rot.vkbd);
972
973              if (rot.vkbd_ctrl_win)
974                {
975                   ELB(ELBT_BD, "SET KBD_OFF", 0);
976                   ecore_x_e_virtual_keyboard_state_set
977                      (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
978                }
979              rot.vkbd_hide_prepare_done = EINA_FALSE;
980
981              if (rot.vkbd_hide_timer)
982                ecore_timer_del(rot.vkbd_hide_timer);
983              rot.vkbd_hide_timer = NULL;
984
985              rot.vkbd_show_prepare_done = EINA_FALSE;
986              if (rot.vkbd_show_prepare_timer)
987                ecore_timer_del(rot.vkbd_show_prepare_timer);
988              rot.vkbd_show_prepare_timer = NULL;
989              if (rot.vkbd_show_timer)
990                ecore_timer_del(rot.vkbd_show_timer);
991              rot.vkbd_show_timer = NULL;
992
993              rot.vkbd = NULL;
994           }
995 #endif
996         eina_hash_del(borders_hash, e_util_winid_str_get(bd->client.win), bd2);
997         eina_hash_del(borders_hash, e_util_winid_str_get(bd2->bg_win), bd2);
998         eina_hash_del(borders_hash, e_util_winid_str_get(bd2->win), bd2);
999      }
1000    eina_hash_add(borders_hash, e_util_winid_str_get(bd->client.win), bd);
1001    eina_hash_add(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
1002    eina_hash_add(borders_hash, e_util_winid_str_get(bd->win), bd);
1003    managed = 1;
1004    ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &managed, 1);
1005    ecore_x_window_prop_card32_set(win, E_ATOM_CONTAINER, &bd->zone->container->num, 1);
1006    ecore_x_window_prop_card32_set(win, E_ATOM_ZONE, &bd->zone->num, 1);
1007      {
1008         unsigned int zgeom[4];
1009         
1010         zgeom[0] = bd->zone->x;
1011         zgeom[1] = bd->zone->y;
1012         zgeom[2] = bd->zone->w;
1013         zgeom[3] = bd->zone->h;
1014         ecore_x_window_prop_card32_set(win, E_ATOM_ZONE_GEOMETRY, zgeom, 4);
1015      }
1016    e_desk_xy_get(bd->desk, &deskx, &desky);
1017    desk[0] = deskx;
1018    desk[1] = desky;
1019    ecore_x_window_prop_card32_set(win, E_ATOM_DESK, desk, 2);
1020 #ifdef _F_USE_DESK_WINDOW_PROFILE_
1021    if (strcmp(bd->desk->window_profile,
1022               e_config->desktop_default_window_profile) != 0)
1023      {
1024         ecore_x_e_window_profile_set(bd->client.win,
1025                                      bd->desk->window_profile);
1026      }
1027 #endif
1028
1029    focus_stack = eina_list_append(focus_stack, bd);
1030
1031    bd->pointer = e_pointer_window_new(bd->win, 0);
1032    return bd;
1033 }
1034
1035 EAPI void
1036 e_border_res_change_geometry_save(E_Border *bd)
1037 {
1038    E_OBJECT_CHECK(bd);
1039    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1040
1041    if (bd->pre_res_change.valid) return;
1042    bd->pre_res_change.valid = 1;
1043    bd->pre_res_change.x = bd->x;
1044    bd->pre_res_change.y = bd->y;
1045    bd->pre_res_change.w = bd->w;
1046    bd->pre_res_change.h = bd->h;
1047    bd->pre_res_change.saved.x = bd->saved.x;
1048    bd->pre_res_change.saved.y = bd->saved.y;
1049    bd->pre_res_change.saved.w = bd->saved.w;
1050    bd->pre_res_change.saved.h = bd->saved.h;
1051 }
1052
1053 EAPI void
1054 e_border_res_change_geometry_restore(E_Border *bd)
1055 {
1056    struct
1057    {
1058       unsigned char valid : 1;
1059       int           x, y, w, h;
1060       struct
1061       {
1062          int x, y, w, h;
1063       } saved;
1064    } pre_res_change;
1065
1066    E_OBJECT_CHECK(bd);
1067    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1068    if (!bd->pre_res_change.valid) return;
1069    if (bd->new_client) return;
1070
1071    ecore_x_window_shadow_tree_flush();
1072    memcpy(&pre_res_change, &bd->pre_res_change, sizeof(pre_res_change));
1073
1074    if (bd->fullscreen)
1075      {
1076         e_border_unfullscreen(bd);
1077         e_border_fullscreen(bd, e_config->fullscreen_policy);
1078      }
1079    else if (bd->maximized != E_MAXIMIZE_NONE)
1080      {
1081         E_Maximize max;
1082
1083         max = bd->maximized;
1084         e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
1085         e_border_maximize(bd, max);
1086      }
1087    else
1088      {
1089         int x, y, w, h, zx, zy, zw, zh;
1090
1091         bd->saved.x = bd->pre_res_change.saved.x;
1092         bd->saved.y = bd->pre_res_change.saved.y;
1093         bd->saved.w = bd->pre_res_change.saved.w;
1094         bd->saved.h = bd->pre_res_change.saved.h;
1095
1096         e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
1097
1098         if (bd->saved.w > zw)
1099           bd->saved.w = zw;
1100         if ((bd->saved.x + bd->saved.w) > (zx + zw))
1101           bd->saved.x = zx + zw - bd->saved.w;
1102
1103         if (bd->saved.h > zh)
1104           bd->saved.h = zh;
1105         if ((bd->saved.y + bd->saved.h) > (zy + zh))
1106           bd->saved.y = zy + zh - bd->saved.h;
1107
1108         x = bd->pre_res_change.x;
1109         y = bd->pre_res_change.y;
1110         w = bd->pre_res_change.w;
1111         h = bd->pre_res_change.h;
1112         if (w > zw)
1113           w = zw;
1114         if (h > zh)
1115           h = zh;
1116         if ((x + w) > (zx + zw))
1117           x = zx + zw - w;
1118         if ((y + h) > (zy + zh))
1119           y = zy + zh - h;
1120         e_border_move_resize(bd, x, y, w, h);
1121      }
1122    memcpy(&bd->pre_res_change, &pre_res_change, sizeof(pre_res_change));
1123 }
1124
1125 EAPI void
1126 e_border_zone_set(E_Border *bd,
1127                   E_Zone   *zone)
1128 {
1129    E_Event_Border_Zone_Set *ev;
1130
1131    E_OBJECT_CHECK(bd);
1132    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1133    E_OBJECT_CHECK(zone);
1134    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1135    if (!zone) return;
1136    if (bd->zone == zone) return;
1137
1138    /* if the window does not lie in the new zone, move it so that it does */
1139    if (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))
1140      {
1141         int x, y;
1142         /* first guess -- get offset from old zone, and apply to new zone */
1143         x = zone->x + (bd->x - bd->zone->x);
1144         y = zone->y + (bd->y - bd->zone->y);
1145
1146         /* keep window from hanging off bottom and left */
1147         if (x + bd->w > zone->x + zone->w) x += (zone->x + zone->w) - (x + bd->w);
1148         if (y + bd->h > zone->y + zone->h) y += (zone->y + zone->h) - (y + bd->h);
1149
1150         /* make sure to and left are on screen (if the window is larger than the zone, it will hang off the bottom / right) */
1151         if (x < zone->x) x = zone->x;
1152         if (y < zone->y) y = zone->y;
1153
1154         if (!E_INTERSECTS(x, y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))
1155           {
1156              /* still not in zone at all, so just move it to closest edge */
1157               if (x < zone->x) x = zone->x;
1158               if (x >= zone->x + zone->w) x = zone->x + zone->w - bd->w;
1159               if (y < zone->y) y = zone->y;
1160               if (y >= zone->y + zone->h) y = zone->y + zone->h - bd->h;
1161           }
1162         e_border_move(bd, x, y);
1163      }
1164
1165    bd->zone = zone;
1166
1167    if (bd->desk->zone != bd->zone)
1168      e_border_desk_set(bd, e_desk_current_get(bd->zone));
1169
1170    ev = E_NEW(E_Event_Border_Zone_Set, 1);
1171    ev->border = bd;
1172    e_object_ref(E_OBJECT(bd));
1173 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_zone_set_event");
1174    ev->zone = zone;
1175    e_object_ref(E_OBJECT(zone));
1176
1177    ecore_event_add(E_EVENT_BORDER_ZONE_SET, ev, _e_border_event_border_zone_set_free, NULL);
1178
1179    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_ZONE, &bd->zone->num, 1);
1180    // XXXXXXXXXXXXXXXXXXXXXXXXX
1181    // XXX ZZZZZZZZZZZZZZZZZZZzz
1182    // need to adjust this if zone pos/size changes
1183      {
1184         unsigned int zgeom[4];
1185         
1186         zgeom[0] = bd->zone->x;
1187         zgeom[1] = bd->zone->y;
1188         zgeom[2] = bd->zone->w;
1189         zgeom[3] = bd->zone->h;
1190         ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_ZONE_GEOMETRY, zgeom, 4);
1191      }
1192    e_remember_update(bd);
1193 }
1194
1195 EAPI void
1196 e_border_desk_set(E_Border *bd,
1197                   E_Desk   *desk)
1198 {
1199    E_Event_Border_Desk_Set *ev;
1200    E_Desk *old_desk;
1201
1202    E_OBJECT_CHECK(bd);
1203    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1204    E_OBJECT_CHECK(desk);
1205    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1206    if (bd->desk == desk) return;
1207    ecore_x_window_shadow_tree_flush();
1208    if (bd->fullscreen)
1209      {
1210         bd->desk->fullscreen_borders--;
1211         desk->fullscreen_borders++;
1212      }
1213    old_desk = bd->desk;
1214    bd->desk = desk;
1215    e_border_zone_set(bd, desk->zone);
1216
1217    _e_border_hook_call(E_BORDER_HOOK_SET_DESK, bd);
1218    e_hints_window_desktop_set(bd);
1219
1220    ev = E_NEW(E_Event_Border_Desk_Set, 1);
1221    ev->border = bd;
1222    e_object_ref(E_OBJECT(bd));
1223 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_desk_set_event");
1224    ev->desk = old_desk;
1225    e_object_ref(E_OBJECT(old_desk));
1226    ecore_event_add(E_EVENT_BORDER_DESK_SET, ev, _e_border_event_border_desk_set_free, NULL);
1227
1228    if (bd->ignore_first_unmap != 1)
1229      {
1230         if ((bd->desk->visible) || (bd->sticky))
1231           e_border_show(bd);
1232         else
1233           e_border_hide(bd, 1);
1234      }
1235
1236    if (e_config->transient.desktop)
1237      {
1238         Eina_List *l;
1239         E_Border *child;
1240         Eina_List *list = _e_border_sub_borders_new(bd);
1241
1242         EINA_LIST_FOREACH(list, l, child)
1243           {
1244              e_border_desk_set(child, bd->desk);
1245           }
1246         eina_list_free(list);
1247      }
1248    e_remember_update(bd);
1249 }
1250
1251 #ifdef _F_ZONE_WINDOW_ROTATION_
1252 static Eina_Bool
1253 _e_border_vkbd_state_check(E_Border *bd,
1254                            Eina_Bool show)
1255 {
1256    Eina_Bool res = EINA_TRUE;
1257    if (!e_config->wm_win_rotation) return EINA_FALSE;
1258    if ((rot.vkbd) && (rot.vkbd == bd))
1259      {
1260         if (show)
1261           {
1262              if ((rot.vkbd_hide_prepare_done) ||
1263                  (rot.vkbd_hide_prepare_timer))
1264                res = EINA_FALSE;
1265           }
1266         else
1267           {
1268              if ((rot.vkbd_show_prepare_done) ||
1269                  (rot.vkbd_show_prepare_timer))
1270                res = EINA_FALSE;
1271           }
1272      }
1273    return res;
1274 }
1275
1276 static Eina_Bool
1277 _e_border_vkbd_show_timeout(void *data)
1278 {
1279    E_Border *bd = data;
1280    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1281    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1282      {
1283         if (_e_border_vkbd_state_check(bd, EINA_TRUE))
1284           {
1285              if (rot.vkbd_ctrl_win)
1286                {
1287                   ELB(ELBT_BD, "SET KBD_ON", 0);
1288                   ecore_x_e_virtual_keyboard_state_set
1289                     (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1290                }
1291           }
1292      }
1293
1294    rot.vkbd_show_prepare_done = EINA_FALSE;
1295
1296    if (rot.vkbd_show_prepare_timer)
1297      ecore_timer_del(rot.vkbd_show_prepare_timer);
1298    rot.vkbd_show_prepare_timer = NULL;
1299
1300    if (rot.vkbd_show_timer)
1301      ecore_timer_del(rot.vkbd_show_timer);
1302    rot.vkbd_show_timer = NULL;
1303
1304    return ECORE_CALLBACK_CANCEL;
1305 }
1306
1307 static Eina_Bool
1308 _e_border_vkbd_hide_timeout(void *data)
1309 {
1310    E_Border *bd = data;
1311    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1312    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1313      {
1314         if (_e_border_vkbd_state_check(bd, EINA_FALSE))
1315           {
1316              if (rot.vkbd_ctrl_win)
1317                {
1318                   ELB(ELBT_BD, "SET KBD_OFF", 0);
1319                   ecore_x_e_virtual_keyboard_state_set
1320                     (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1321                }
1322           }
1323         e_object_unref(E_OBJECT(bd));
1324      }
1325
1326    rot.vkbd_hide_prepare_done = EINA_FALSE;
1327
1328    if (rot.vkbd_hide_prepare_timer)
1329      ecore_timer_del(rot.vkbd_hide_prepare_timer);
1330    rot.vkbd_hide_prepare_timer = NULL;
1331
1332    if (rot.vkbd_hide_timer)
1333      ecore_timer_del(rot.vkbd_hide_timer);
1334    rot.vkbd_hide_timer = NULL;
1335
1336    return ECORE_CALLBACK_CANCEL;
1337 }
1338
1339 static void
1340 _e_border_vkbd_show(E_Border *bd)
1341 {
1342    if (!e_config->wm_win_rotation) return;
1343    rot.vkbd_show_prepare_done = EINA_TRUE;
1344    if (rot.vkbd_show_prepare_timer)
1345      ecore_timer_del(rot.vkbd_show_prepare_timer);
1346    rot.vkbd_show_prepare_timer = NULL;
1347    if (rot.vkbd_show_timer)
1348      ecore_timer_del(rot.vkbd_show_timer);
1349    rot.vkbd_show_timer = NULL;
1350    if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
1351      {
1352         e_border_show(bd);
1353         rot.vkbd_show_timer = ecore_timer_add(0.1f, _e_border_vkbd_show_timeout, bd);
1354      }
1355 }
1356
1357 static void
1358 _e_border_vkbd_hide(E_Border *bd)
1359 {
1360    if (!e_config->wm_win_rotation) return;
1361    rot.vkbd_hide_prepare_done = EINA_TRUE;
1362    if (rot.vkbd_hide_prepare_timer)
1363      ecore_timer_del(rot.vkbd_hide_prepare_timer);
1364    rot.vkbd_hide_prepare_timer = NULL;
1365    if (rot.vkbd_hide_timer)
1366      ecore_timer_del(rot.vkbd_hide_timer);
1367    rot.vkbd_hide_timer = NULL;
1368    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1369      {
1370         ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
1371         e_border_hide(bd, 0);
1372         if (!e_object_is_del(E_OBJECT(bd)))
1373           {
1374              ELB(ELBT_BD, "DEL VKBD", bd->client.win);
1375              e_object_del(E_OBJECT(bd));
1376           }
1377         rot.vkbd_hide_timer = ecore_timer_add(0.03f, _e_border_vkbd_hide_timeout, bd);
1378      }
1379 }
1380
1381 static Eina_Bool
1382 _e_border_vkbd_show_prepare_timeout(void *data)
1383 {
1384    E_Border *bd = data;
1385    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1386    if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
1387      {
1388         ELB(ELBT_BD, "TIMEOUT KBD_SHOW_PREPARE", bd->client.win);
1389         _e_border_vkbd_show(bd);
1390      }
1391    return ECORE_CALLBACK_CANCEL;
1392 }
1393
1394 static Eina_Bool
1395 _e_border_vkbd_hide_prepare_timeout(void *data)
1396 {
1397    E_Border *bd = data;
1398    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1399    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1400      {
1401         ELB(ELBT_BD, "TIMEOUT KBD_HIDE_PREPARE", bd->client.win);
1402         _e_border_vkbd_hide(bd);
1403      }
1404    return ECORE_CALLBACK_CANCEL;
1405 }
1406 #endif
1407
1408 EAPI void
1409 e_border_show(E_Border *bd)
1410 {
1411    E_Event_Border_Show *ev;
1412    unsigned int visible;
1413
1414    E_OBJECT_CHECK(bd);
1415    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1416    if (bd->visible) return;
1417 #ifdef _F_ZONE_WINDOW_ROTATION_
1418    // newly created window that has to be rotated will be show after rotation done.
1419    // so, skip at this time. it will be called again after GETTING ROT_DONE.
1420    if ((bd->new_client) &&
1421        (bd->client.e.state.rot.changes != -1))
1422      {
1423         ELB(ELBT_BD, "PENDING SHOW UNTIL GETTING ROT_DONE", bd->client.win);
1424         // if this window is in withdrawn state, set the normal state
1425         // that's because the window in withdrawn state can't render its canvas.
1426         // eventually, this window will not send the message of rotation done,
1427         // even if e17 request to rotation this window.
1428         if (bd->client.icccm.state != ECORE_X_WINDOW_STATE_HINT_NORMAL)
1429           e_hints_window_visible_set(bd);
1430
1431         bd->client.e.state.rot.pending_show = 1;
1432         return;
1433      }
1434    if ((e_config->wm_win_rotation) &&
1435        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
1436        (bd == rot.vkbd) &&
1437        (!rot.vkbd_show_prepare_done))
1438      {
1439         ELB(ELBT_BD, "SEND KBD_ON_PREPARE", bd->client.win);
1440         ecore_x_e_virtual_keyboard_on_prepare_request_send(rot.vkbd_ctrl_win);
1441         if (rot.vkbd_show_prepare_timer)
1442           ecore_timer_del(rot.vkbd_show_prepare_timer);
1443         rot.vkbd_show_prepare_timer = ecore_timer_add(1.5f,
1444                                                       _e_border_vkbd_show_prepare_timeout,
1445                                                       bd);
1446         return;
1447      }
1448    ELB(ELBT_BD, "SHOW", bd->client.win);
1449 #endif
1450    ecore_x_window_shadow_tree_flush();
1451    e_container_shape_show(bd->shape);
1452    if (!bd->need_reparent)
1453      ecore_x_window_show(bd->client.win);
1454    e_hints_window_visible_set(bd);
1455    bd->hidden = 0;
1456    bd->visible = 1;
1457    bd->changes.visible = 1;
1458
1459    visible = 1;
1460    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
1461    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
1462
1463    ev = E_NEW(E_Event_Border_Show, 1);
1464    ev->border = bd;
1465    e_object_ref(E_OBJECT(bd));
1466 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_show_event");
1467    ecore_event_add(E_EVENT_BORDER_SHOW, ev, _e_border_event_border_show_free, NULL);
1468
1469 #ifdef _F_ZONE_WINDOW_ROTATION_
1470    if ((e_config->wm_win_rotation) &&
1471        ((bd->client.e.state.rot.support) ||
1472         (bd->client.e.state.rot.app_set)))
1473      {
1474         ELB(ELBT_ROT, "CHECK", bd->client.win);
1475         int rotation = _e_border_rotation_angle_get(bd);
1476         if (rotation != -1) e_border_rotation_set(bd, rotation);
1477      }
1478 #endif
1479 }
1480
1481 EAPI void
1482 e_border_hide(E_Border *bd,
1483               int       manage)
1484 {
1485    unsigned int visible;
1486
1487    E_OBJECT_CHECK(bd);
1488    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1489
1490 #ifdef _F_ZONE_WINDOW_ROTATION_
1491    if ((e_config->wm_win_rotation) &&
1492        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
1493        (bd == rot.vkbd) &&
1494        (!rot.vkbd_hide_prepare_done) &&
1495        (!bd->iconic))
1496      {
1497         Eina_Bool need_prepare = EINA_TRUE;
1498         E_Border *child = NULL;
1499         if (bd->parent)
1500           {
1501              if (e_object_is_del(E_OBJECT(bd->parent)))
1502                need_prepare = EINA_FALSE;
1503              else
1504                {
1505                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
1506                   if (bd->parent->modal == bd)
1507                     {
1508                        ecore_x_event_mask_unset(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
1509                        ecore_x_event_mask_set(bd->parent->client.win, bd->parent->saved.event_mask);
1510                        bd->parent->lock_close = 0;
1511                        bd->parent->saved.event_mask = 0;
1512                        bd->parent->modal = NULL;
1513                     }
1514                   bd->parent = NULL;
1515                }
1516           }
1517         else
1518           need_prepare = EINA_FALSE;
1519
1520         EINA_LIST_FREE(bd->transients, child)
1521           {
1522              child->parent = NULL;
1523           }
1524
1525         ELBF(ELBT_BD, 0, bd->client.win, "SEND KBD_OFF_PREPARE:%d", need_prepare);
1526
1527         if (need_prepare)
1528           {
1529              e_object_ref(E_OBJECT(bd));
1530              ecore_x_e_virtual_keyboard_off_prepare_request_send(rot.vkbd_ctrl_win);
1531              if (rot.vkbd_hide_prepare_timer)
1532                ecore_timer_del(rot.vkbd_hide_prepare_timer);
1533              rot.vkbd_hide_prepare_timer = ecore_timer_add(1.5f,
1534                                                            _e_border_vkbd_hide_prepare_timeout,
1535                                                            bd);
1536              return;
1537           }
1538         else
1539           {
1540              e_object_ref(E_OBJECT(bd));
1541
1542              /* In order to clear conformant area properly, WM should send keyboard off prepare request event */
1543              ecore_x_e_virtual_keyboard_off_prepare_request_send(rot.vkbd_ctrl_win);
1544
1545              /* cleanup code from _e_border_vkbd_hide() */
1546              rot.vkbd_hide_prepare_done = EINA_TRUE;
1547              if (rot.vkbd_hide_prepare_timer)
1548                ecore_timer_del(rot.vkbd_hide_prepare_timer);
1549              rot.vkbd_hide_prepare_timer = NULL;
1550              if (rot.vkbd_hide_timer)
1551                ecore_timer_del(rot.vkbd_hide_timer);
1552              rot.vkbd_hide_timer = ecore_timer_add(0.03f, _e_border_vkbd_hide_timeout, bd);
1553           }
1554      }
1555    ELBF(ELBT_BD, 0, bd->client.win, "HIDE visible:%d", bd->visible);
1556 #endif
1557    if (!bd->visible) goto send_event;
1558    ecore_x_window_shadow_tree_flush();
1559    if (bd->moving)
1560      _e_border_move_end(bd);
1561    if (bd->resize_mode != RESIZE_NONE)
1562      {
1563         _e_border_pointer_resize_end(bd);
1564         bd->resize_mode = RESIZE_NONE;
1565         _e_border_resize_end(bd);
1566      }
1567
1568    e_container_shape_hide(bd->shape);
1569    if (!bd->iconic) e_hints_window_hidden_set(bd);
1570
1571    bd->visible = 0;
1572    bd->changes.visible = 1;
1573
1574    if (!bd->need_reparent)
1575      {
1576         if ((bd->focused) ||
1577             (e_grabinput_last_focus_win_get() == bd->client.win))
1578           {
1579              e_border_focus_set(bd, 0, 1);
1580              if (manage != 2)
1581                {
1582                   E_Border *pbd;
1583                   E_Container *con;
1584                   E_Zone *zone;
1585                   E_Desk *desk;
1586
1587                   con = e_container_current_get(e_manager_current_get());
1588                   zone = e_zone_current_get(con);
1589                   desk = e_desk_current_get(zone);
1590
1591                   if ((bd->parent) &&
1592                       (bd->parent->desk == desk) && (bd->parent->modal == bd))
1593                     e_border_focus_set(bd->parent, 1, 1);
1594                   else if (e_config->focus_revert_on_hide_or_close)
1595                     {
1596                        /* When using pointer focus, the border under the
1597                         * pointer (if any) gets focused, in sloppy/click
1598                         * focus the last focused window on the current
1599                         * desk gets focus */
1600                        if (e_config->focus_policy == E_FOCUS_MOUSE)
1601                          {
1602                             pbd = e_border_under_pointer_get(desk, bd);
1603                             if (pbd)
1604                               e_border_focus_set(pbd, 1, 1);
1605                          }
1606 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
1607                        else if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) &&
1608                                 (e_config->focus_policy == E_FOCUS_CLICK))
1609                          _e_border_latest_stacked_focus(bd);
1610 #endif
1611
1612                        else
1613                          e_desk_last_focused_focus(desk);
1614                     }
1615                }
1616           }
1617         switch (manage)
1618           {
1619            case 2: break;
1620            case 3:
1621              bd->hidden = 1;
1622            case 1:
1623              /* Make sure that this border isn't deleted */
1624              bd->await_hide_event++;
1625            default:
1626              if (!e_manager_comp_evas_get(bd->zone->container->manager))
1627                ecore_x_window_hide(bd->client.win);
1628           }
1629      }
1630
1631    visible = 0;
1632    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
1633    if (!manage)
1634      ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
1635
1636    bd->post_show = 0;
1637
1638 send_event:
1639    if (!stopping)
1640      {
1641 #ifdef _F_ZONE_WINDOW_ROTATION_
1642         _e_border_rotation_list_remove(bd);
1643 #endif
1644
1645         E_Event_Border_Hide *ev;
1646
1647         ev = E_NEW(E_Event_Border_Hide, 1);
1648         ev->border = bd;
1649         e_object_ref(E_OBJECT(bd));
1650 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_hide_event");
1651         ecore_event_add(E_EVENT_BORDER_HIDE, ev, _e_border_event_border_hide_free, NULL);
1652      }
1653 }
1654
1655 static void
1656 _pri_adj(int pid, int set, int adj, Eina_Bool use_adj, Eina_Bool adj_children, Eina_Bool do_children)
1657 {
1658    int newpri = set;
1659
1660    if (use_adj) newpri = getpriority(PRIO_PROCESS, pid) + adj;
1661    setpriority(PRIO_PROCESS, pid, newpri);
1662 // shouldnt need to do this as default ionice class is "none" (0), and
1663 // this inherits io priority FROM nice level
1664 //        ioprio_set(IOPRIO_WHO_PROCESS, pid,
1665 //                   IOPRIO_PRIO_VALUE(2, 5));
1666    if (do_children)
1667      {
1668         Eina_List *files;
1669         char *file, buf[PATH_MAX];
1670         FILE *f;
1671         int pid2, ppid;
1672
1673         // yes - this is /proc specific... so this may not work on some
1674         // os's - works on linux. too bad for others.
1675         files = ecore_file_ls("/proc");
1676         EINA_LIST_FREE(files, file)
1677           {
1678              if (isdigit(file[0]))
1679                {
1680                   snprintf(buf, sizeof(buf), "/proc/%s/stat", file);
1681                   f = fopen(buf, "r");
1682                   if (f)
1683                     {
1684                        pid2 = -1;
1685                        ppid = -1;
1686                        if (fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid) == 2)
1687                          {
1688                             fclose(f);
1689                             if (ppid == pid)
1690                               {
1691                                  if (adj_children)
1692                                     _pri_adj(pid2, set, adj, EINA_TRUE,
1693                                              adj_children, do_children);
1694                                  else
1695                                     _pri_adj(pid2, set, adj, use_adj,
1696                                              adj_children, do_children);
1697                               }
1698                          }
1699                        else fclose(f);
1700                     }
1701                }
1702              free(file);
1703           }
1704      }
1705 }
1706
1707 static void
1708 _e_border_pri_raise(E_Border *bd)
1709 {
1710    if (bd->client.netwm.pid <= 0) return;
1711    if (bd->client.netwm.pid == getpid()) return;
1712    _pri_adj(bd->client.netwm.pid,
1713             e_config->priority - 1, -1, EINA_FALSE,
1714 //            EINA_TRUE, EINA_TRUE);
1715             EINA_TRUE, EINA_FALSE);
1716 //   printf("WIN: pid %i, title %s (HI!!!!!!!!!!!!!!!!!!)\n",
1717 //          bd->client.netwm.pid, e_border_name_get(bd));
1718 }
1719
1720 static void
1721 _e_border_pri_norm(E_Border *bd)
1722 {
1723    if (bd->client.netwm.pid <= 0) return;
1724    if (bd->client.netwm.pid == getpid()) return;
1725    _pri_adj(bd->client.netwm.pid,
1726             e_config->priority, 1, EINA_FALSE,
1727 //            EINA_TRUE, EINA_TRUE);
1728             EINA_TRUE, EINA_FALSE);
1729 //   printf("WIN: pid %i, title %s (NORMAL)\n",
1730 //          bd->client.netwm.pid, e_border_name_get(bd));
1731 }
1732
1733 static void
1734 _e_border_frame_replace(E_Border *bd, Eina_Bool argb)
1735 {
1736    Ecore_X_Window win;
1737    Ecore_Evas *bg_ecore_evas;
1738    char buf[4096];
1739
1740    bd->argb = argb;
1741
1742    win = bd->win;
1743    bg_ecore_evas = bd->bg_ecore_evas;
1744
1745    /* unregister old frame window */
1746    eina_hash_del(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
1747    eina_hash_del(borders_hash, e_util_winid_str_get(bd->win), bd);
1748
1749    e_focus_setdown(bd);
1750    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
1751    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
1752
1753    if (bd->icon_object)
1754      evas_object_del(bd->icon_object);
1755
1756    evas_object_del(bd->bg_object);
1757    e_canvas_del(bg_ecore_evas);
1758    ecore_evas_free(bg_ecore_evas);
1759
1760    if (bd->pointer)
1761      e_object_del(E_OBJECT(bd->pointer));
1762
1763    /* create new frame */
1764    if (argb)
1765      bd->win = ecore_x_window_manager_argb_new(bd->zone->container->win,
1766                  bd->x, bd->y, bd->w, bd->h);
1767    else
1768      {
1769         bd->win = ecore_x_window_override_new(bd->zone->container->win,
1770                 bd->x, bd->y, bd->w, bd->h);
1771         ecore_x_window_shape_events_select(bd->win, 1);
1772      }
1773
1774    ecore_x_window_configure(bd->win,
1775           ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
1776           ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
1777           0, 0, 0, 0, 0,
1778           win, ECORE_X_WINDOW_STACK_BELOW);
1779
1780    e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
1781    e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
1782    e_focus_setup(bd);
1783
1784    bd->bg_ecore_evas = e_canvas_new(bd->win,
1785                                     0, 0, bd->w, bd->h, 1, 0,
1786                                     &(bd->bg_win));
1787
1788    e_canvas_add(bd->bg_ecore_evas);
1789    ecore_x_window_reparent(bd->event_win, bd->win, 0, 0);
1790
1791    bd->bg_evas = ecore_evas_get(bd->bg_ecore_evas);
1792    ecore_evas_name_class_set(bd->bg_ecore_evas, "E", "Frame_Window");
1793    ecore_evas_title_set(bd->bg_ecore_evas, "Enlightenment Frame");
1794
1795    ecore_x_window_shape_events_select(bd->bg_win, 1);
1796
1797    /* move client with shell win over to new frame */
1798    ecore_x_window_reparent(bd->client.shell_win, bd->win,
1799          bd->client_inset.l, bd->client_inset.t);
1800
1801    bd->pointer = e_pointer_window_new(bd->win, 0);
1802
1803    eina_hash_add(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
1804    eina_hash_add(borders_hash, e_util_winid_str_get(bd->win), bd);
1805
1806    if (bd->visible)
1807      {
1808         E_Border *tmp;
1809         Eina_List *l;
1810
1811         ecore_evas_show(bd->bg_ecore_evas);
1812         ecore_x_window_show(bd->win);
1813
1814         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
1815           ecore_x_window_show(tmp->win);
1816      }
1817
1818    bd->bg_object = edje_object_add(bd->bg_evas);
1819    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
1820    e_theme_edje_object_set(bd->bg_object, "base/theme/borders", buf);
1821
1822    bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
1823
1824    /* cleanup old frame */
1825    ecore_x_window_free(win);
1826 }
1827
1828 static void
1829 _e_border_client_move_resize_send(E_Border *bd)
1830 {
1831    if (bd->internal_ecore_evas)
1832      ecore_evas_managed_move(bd->internal_ecore_evas,
1833                              bd->x + bd->fx.x + bd->client_inset.l,
1834                              bd->y + bd->fx.y + bd->client_inset.t);
1835
1836    ecore_x_icccm_move_resize_send(bd->client.win,
1837                                   bd->x + bd->fx.x + bd->client_inset.l,
1838                                   bd->y + bd->fx.y + bd->client_inset.t,
1839                                   bd->client.w,
1840                                   bd->client.h);
1841 }
1842
1843 static void
1844 _e_border_pending_move_resize_add(E_Border    *bd,
1845                                   int          move,
1846                                   int          resize,
1847                                   int          x,
1848                                   int          y,
1849                                   int          w,
1850                                   int          h,
1851                                   Eina_Bool    without_border,
1852                                   unsigned int serial)
1853 {
1854    E_Border_Pending_Move_Resize *pnd;
1855
1856    pnd = E_NEW(E_Border_Pending_Move_Resize, 1);
1857    if (!pnd) return;
1858    pnd->resize = resize;
1859    pnd->move = move;
1860    pnd->without_border = without_border;
1861    pnd->x = x;
1862    pnd->y = y;
1863    pnd->w = w;
1864    pnd->h = h;
1865    pnd->serial = serial;
1866    bd->pending_move_resize = eina_list_append(bd->pending_move_resize, pnd);
1867 }
1868
1869 static void
1870 _e_border_move_internal(E_Border *bd,
1871                         int       x,
1872                         int       y,
1873                         Eina_Bool without_border)
1874 {
1875    E_Event_Border_Move *ev;
1876
1877    E_OBJECT_CHECK(bd);
1878    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1879
1880    ecore_x_window_shadow_tree_flush();
1881    if (bd->new_client)
1882      {
1883         _e_border_pending_move_resize_add(bd, 1, 0, x, y, 0, 0, without_border, 0);
1884         return;
1885      }
1886
1887    if (bd->maximized)
1888      {
1889        if ((bd->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_BOTH)
1890          {
1891             if (e_config->allow_manip)
1892               bd->maximized = 0;
1893
1894             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
1895               {
1896                   x = bd->x;
1897               }
1898             else
1899             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
1900               {
1901                   y = bd->y;
1902               }
1903          }
1904        else if (e_config->allow_manip)
1905          bd->maximized = 0;
1906        else
1907          return;
1908      }
1909
1910    if (without_border)
1911      {
1912         x -= bd->client_inset.l;
1913         y -= bd->client_inset.t;
1914      }
1915    if (bd->move_intercept_cb)
1916      {
1917         int px, py;
1918         px = bd->x, py = bd->y;
1919         bd->move_intercept_cb(bd, x, y);
1920         if ((bd->x == px) && (bd->y == py)) return;
1921      }
1922    else if ((x == bd->x) && (y == bd->y)) return;
1923    bd->pre_res_change.valid = 0;
1924    bd->x = x;
1925    bd->y = y;
1926    bd->changed = 1;
1927    bd->changes.pos = 1;
1928 #if 0
1929    if (bd->client.netwm.sync.request)
1930      {
1931         bd->client.netwm.sync.wait++;
1932         ecore_x_netwm_sync_request_send(bd->client.win, bd->client.netwm.sync.serial++);
1933      }
1934 #endif
1935    _e_border_client_move_resize_send(bd);
1936    _e_border_move_update(bd);
1937    ev = E_NEW(E_Event_Border_Move, 1);
1938    ev->border = bd;
1939    e_object_ref(E_OBJECT(bd));
1940 //  e_object_breadcrumb_add(E_OBJECT(bd), "border_move_event");
1941    ecore_event_add(E_EVENT_BORDER_MOVE, ev, _e_border_event_border_move_free, NULL);
1942    _e_border_zone_update(bd);
1943 }
1944
1945 /**
1946  * Move window to coordinates that already account border decorations.
1947  *
1948  * This call will consider given position already accounts border
1949  * decorations, so it will not be considered later. This will just
1950  * work properly with borders that have being evaluated and border
1951  * decorations are known (border->client_inset).
1952  *
1953  * @parm x horizontal position to place window.
1954  * @parm y vertical position to place window.
1955  *
1956  * @see e_border_move_without_border()
1957  */
1958 EAPI void
1959 e_border_move(E_Border *bd,
1960               int       x,
1961               int       y)
1962 {
1963    if (bd->fullscreen)
1964      return;
1965
1966    _e_border_move_internal(bd, x, y, 0);
1967 }
1968
1969
1970 /**
1971  * Set a callback which will be called just prior to updating the
1972  * move coordinates for a border
1973  */
1974 EAPI void
1975 e_border_move_intercept_cb_set(E_Border *bd, E_Border_Move_Intercept_Cb cb)
1976 {
1977    bd->move_intercept_cb = cb;
1978 }
1979
1980 /**
1981  * Move window to coordinates that do not account border decorations yet.
1982  *
1983  * This call will consider given position does not account border
1984  * decoration, so these values (border->client_inset) will be
1985  * accounted automatically. This is specially useful when it is a new
1986  * client and has not be evaluated yet, in this case
1987  * border->client_inset will be zeroed and no information is known. It
1988  * will mark pending requests so border will be accounted on
1989  * evalutation phase.
1990  *
1991  * @parm x horizontal position to place window.
1992  * @parm y vertical position to place window.
1993  *
1994  * @see e_border_move()
1995  */
1996 EAPI void
1997 e_border_move_without_border(E_Border *bd,
1998                              int       x,
1999                              int       y)
2000 {
2001    if (bd->fullscreen)
2002      return;
2003
2004    _e_border_move_internal(bd, x, y, 1);
2005 }
2006
2007 EAPI void
2008 e_border_center(E_Border *bd)
2009 {
2010    int x, y, w, h;
2011    E_OBJECT_CHECK(bd);
2012    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2013
2014    e_zone_useful_geometry_get(bd->zone, &x, &y, &w, &h);
2015    e_border_move(bd, x + (w - bd->w) / 2, y + (h - bd->h) / 2);
2016 }
2017
2018 EAPI void
2019 e_border_center_pos_get(E_Border *bd,
2020                         int      *x,
2021                         int      *y)
2022 {
2023    int zx, zy, zw, zh;
2024    E_OBJECT_CHECK(bd);
2025    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2026
2027    e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
2028    if (x) *x = zx + (zw - bd->w) / 2;
2029    if (y) *y = zy + (zh - bd->h) / 2;
2030 }
2031
2032 EAPI void
2033 e_border_fx_offset(E_Border *bd,
2034                    int       x,
2035                    int       y)
2036 {
2037    E_OBJECT_CHECK(bd);
2038    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2039
2040    if ((x == bd->fx.x) && (y == bd->fx.y)) return;
2041    bd->fx.x = x;
2042    bd->fx.y = y;
2043
2044    bd->changes.pos = 1;
2045    bd->changed = 1;
2046
2047    if (bd->moving) _e_border_move_update(bd);
2048 }
2049
2050 static void
2051 _e_border_move_resize_internal(E_Border *bd,
2052                                int       x,
2053                                int       y,
2054                                int       w,
2055                                int       h,
2056                                Eina_Bool without_border,
2057                                Eina_Bool move)
2058 {
2059    E_Event_Border_Move *mev;
2060    E_Event_Border_Resize *rev;
2061
2062    E_OBJECT_CHECK(bd);
2063    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2064
2065    ecore_x_window_shadow_tree_flush();
2066
2067    if (bd->new_client)
2068      {
2069         _e_border_pending_move_resize_add(bd, move, 1, x, y, w, h, without_border, 0);
2070         return;
2071      }
2072
2073    if (bd->maximized)
2074      {
2075        if ((bd->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_BOTH)
2076          {
2077             if (e_config->allow_manip)
2078               bd->maximized = 0;
2079
2080             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
2081               {
2082                   x = bd->x;
2083                   w = bd->w;
2084               }
2085             else
2086             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
2087               {
2088                   y = bd->y;
2089                   h = bd->h;
2090               }
2091          }
2092        else
2093        if (e_config->allow_manip)
2094          bd->maximized = 0;
2095        else
2096          return;
2097      }
2098
2099    if (without_border)
2100      {
2101         x -= bd->client_inset.l;
2102         y -= bd->client_inset.t;
2103         w += (bd->client_inset.l + bd->client_inset.r);
2104         h += (bd->client_inset.t + bd->client_inset.b);
2105      }
2106
2107    if ((!move || ((x == bd->x) && (y == bd->y))) &&
2108        (w == bd->w) && (h == bd->h))
2109      return;
2110
2111    bd->pre_res_change.valid = 0;
2112    if (move)
2113      {
2114         bd->changes.pos = 1;
2115         bd->x = x;
2116         bd->y = y;
2117      }
2118    bd->w = w;
2119    bd->h = h;
2120    bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
2121    bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
2122
2123    if ((bd->shaped) || (bd->client.shaped))
2124      {
2125         bd->need_shape_merge = 1;
2126         bd->need_shape_export = 1;
2127      }
2128    if (bd->shaped_input)
2129      {
2130         bd->need_shape_merge = 1;
2131      }
2132
2133    if (bd->internal_ecore_evas)
2134      {
2135         bd->changed = 1;
2136         bd->changes.size = 1;
2137      }
2138    else
2139      {
2140         if (bdresize && bd->client.netwm.sync.request)
2141           {
2142              bd->client.netwm.sync.wait++;
2143              /* Don't use x and y as supplied to this function, as it is called with 0, 0
2144               * when no move is intended.  The border geometry is set above anyways.
2145               */
2146              _e_border_pending_move_resize_add(bd, move, 1, bd->x, bd->y, bd->w, bd->h, without_border,
2147                                                bd->client.netwm.sync.serial);
2148              ecore_x_netwm_sync_request_send(bd->client.win,
2149                                              bd->client.netwm.sync.serial++);
2150           }
2151         else
2152           {
2153              bd->changed = 1;
2154              bd->changes.size = 1;
2155           }
2156      }
2157
2158    _e_border_client_move_resize_send(bd);
2159
2160    _e_border_resize_update(bd);
2161    if (move)
2162      {
2163         mev = E_NEW(E_Event_Border_Move, 1);
2164         mev->border = bd;
2165         e_object_ref(E_OBJECT(bd));
2166         //   e_object_breadcrumb_add(E_OBJECT(bd), "border_move_event");
2167         ecore_event_add(E_EVENT_BORDER_MOVE, mev, _e_border_event_border_move_free, NULL);
2168      }
2169
2170    rev = E_NEW(E_Event_Border_Resize, 1);
2171    rev->border = bd;
2172    e_object_ref(E_OBJECT(bd));
2173 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
2174    ecore_event_add(E_EVENT_BORDER_RESIZE, rev, _e_border_event_border_resize_free, NULL);
2175    _e_border_zone_update(bd);
2176 }
2177
2178 /**
2179  * Move and resize window to values that already account border decorations.
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_without_border()
2192  */
2193 EAPI void
2194 e_border_move_resize(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, 0, 1);
2204 }
2205
2206 /**
2207  * Move and resize window to values that do not account border decorations yet.
2208  *
2209  * This call will consider given values 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 x horizontal position to place window.
2215  * @parm y vertical position to place window.
2216  * @parm w horizontal window size.
2217  * @parm h vertical window size.
2218  *
2219  * @see e_border_move_resize()
2220  */
2221 EAPI void
2222 e_border_move_resize_without_border(E_Border *bd,
2223                                     int       x,
2224                                     int       y,
2225                                     int       w,
2226                                     int       h)
2227 {
2228    if (bd->fullscreen)
2229      return;
2230
2231    _e_border_move_resize_internal(bd, x, y, w, h, 1, 1);
2232 }
2233
2234 /**
2235  * Resize window to values that already account border decorations.
2236  *
2237  * This call will consider given size already accounts border
2238  * decorations, so it will not be considered later. This will just
2239  * work properly with borders that have being evaluated and border
2240  * decorations are known (border->client_inset).
2241  *
2242  * @parm w horizontal window size.
2243  * @parm h vertical window size.
2244  *
2245  * @see e_border_resize_without_border()
2246  */
2247 EAPI void
2248 e_border_resize(E_Border *bd,
2249                 int       w,
2250                 int       h)
2251 {
2252    if (bd->fullscreen)
2253      return;
2254
2255    _e_border_move_resize_internal(bd, 0, 0, w, h, 0, 0);
2256 }
2257
2258 #ifdef _F_ZONE_WINDOW_ROTATION_
2259 EAPI Eina_Bool
2260 e_border_rotation_set(E_Border *bd, int rotation)
2261 {
2262    return _e_border_rotation_set_internal(bd, rotation, NULL);
2263 }
2264 #endif
2265
2266 /**
2267  * Resize window to values that do not account border decorations yet.
2268  *
2269  * This call will consider given size does not account border
2270  * decoration, so these values (border->client_inset) will be
2271  * accounted automatically. This is specially useful when it is a new
2272  * client and has not be evaluated yet, in this case
2273  * border->client_inset will be zeroed and no information is known. It
2274  * will mark pending requests so border will be accounted on
2275  * evalutation phase.
2276  *
2277  * @parm w horizontal window size.
2278  * @parm h vertical window size.
2279  *
2280  * @see e_border_resize()
2281  */
2282 EAPI void
2283 e_border_resize_without_border(E_Border *bd,
2284                                int       w,
2285                                int       h)
2286 {
2287    if (bd->fullscreen)
2288      return;
2289
2290    _e_border_move_resize_internal(bd, 0, 0, w, h, 1, 0);
2291 }
2292
2293 EAPI void
2294 e_border_layer_set(E_Border *bd,
2295                    int       layer)
2296 {
2297    int oldraise;
2298
2299    E_OBJECT_CHECK(bd);
2300    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2301
2302    ecore_x_window_shadow_tree_flush();
2303
2304    oldraise = e_config->transient.raise;
2305
2306    if (bd->fullscreen)
2307      {
2308         bd->saved.layer = layer;
2309         return;
2310      }
2311    bd->layer = layer;
2312    if (e_config->transient.layer)
2313      {
2314         Eina_List *l;
2315         E_Border *child;
2316         Eina_List *list = _e_border_sub_borders_new(bd);
2317
2318         /* We need to set raise to one, else the child wont
2319          * follow to the new layer. It should be like this,
2320          * even if the user usually doesn't want to raise
2321          * the transients.
2322          */
2323         e_config->transient.raise = 1;
2324         EINA_LIST_FOREACH(list, l, child)
2325           {
2326              e_border_layer_set(child, layer);
2327           }
2328      }
2329    e_border_raise(bd);
2330    e_config->transient.raise = oldraise;
2331 }
2332
2333 EAPI void
2334 e_border_raise(E_Border *bd)
2335 {
2336    E_Event_Border_Stack *ev;
2337    E_Border *last = NULL, *child;
2338    Eina_List *l;
2339
2340    E_OBJECT_CHECK(bd);
2341    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2342
2343    ecore_x_window_shadow_tree_flush();
2344
2345    if (e_config->transient.raise)
2346      {
2347 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2348         if (e_config->focus_setting != E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
2349           {
2350 #endif
2351         Eina_List *list = _e_border_sub_borders_new(bd);
2352
2353         EINA_LIST_REVERSE_FOREACH(list, l, child)
2354           {
2355              /* Don't stack iconic transients. If the user wants these shown,
2356               * thats another option.
2357               */
2358              if (!child->iconic)
2359                {
2360                   if (last)
2361                     e_border_stack_below(child, last);
2362                   else
2363                     {
2364                        E_Border *above;
2365
2366                        /* First raise the border to find out which border we will end up above */
2367                        above = e_container_border_raise(child);
2368
2369                        if (above)
2370                          {
2371                             /* We ended up above a border, now we must stack this border to
2372                              * generate the stacking event, and to check if this transient
2373                              * has other transients etc.
2374                              */
2375                             e_border_stack_above(child, above);
2376                          }
2377                        else
2378                          {
2379                             /* If we didn't end up above any border, we are on the bottom! */
2380                             e_border_lower(child);
2381                          }
2382                     }
2383                   last = child;
2384                }
2385           }
2386         eina_list_free(list);
2387 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2388           }
2389         else
2390           {
2391              EINA_LIST_FOREACH(bd->transients, l, child)
2392                {
2393                 /* Don't stack iconic transients. If the user wants these shown,
2394                  * thats another option.
2395                  */
2396                   if (!child->iconic)
2397                     {
2398                        child->layer = bd->layer;
2399                        if (!last) last = child;
2400                        e_border_raise (child);
2401                     }
2402                }
2403           }
2404 #endif
2405      }
2406
2407    ev = E_NEW(E_Event_Border_Stack, 1);
2408    ev->border = bd;
2409    e_object_ref(E_OBJECT(bd));
2410
2411    if (last)
2412      {
2413         e_container_border_stack_below(bd, last);
2414         ev->stack = last;
2415         e_object_ref(E_OBJECT(last));
2416         ev->type = E_STACKING_BELOW;
2417      }
2418    else
2419      {
2420         E_Border *above;
2421
2422         /* If we don't have any children, raise this border */
2423         above = e_container_border_raise(bd);
2424         e_border_raise_latest_set(bd);
2425         if (above)
2426           {
2427              /* We ended up above a border */
2428               ev->stack = above;
2429               e_object_ref(E_OBJECT(above));
2430               ev->type = E_STACKING_ABOVE;
2431           }
2432         else
2433           {
2434              /* No border to raise above, same as a lower! */
2435               ev->stack = NULL;
2436               ev->type = E_STACKING_ABOVE;
2437           }
2438      }
2439
2440    ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2441    e_remember_update(bd);
2442 }
2443
2444 EAPI void
2445 e_border_lower(E_Border *bd)
2446 {
2447    E_Event_Border_Stack *ev;
2448    E_Border *last = NULL, *child;
2449    Eina_List *l;
2450
2451    E_OBJECT_CHECK(bd);
2452    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2453
2454    ecore_x_window_shadow_tree_flush();
2455
2456    if (e_config->transient.lower)
2457      {
2458 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2459         if (e_config->focus_setting != E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
2460           {
2461 #endif
2462         Eina_List *list = _e_border_sub_borders_new(bd);
2463
2464         EINA_LIST_REVERSE_FOREACH(list, l, child)
2465           {
2466              /* Don't stack iconic transients. If the user wants these shown,
2467               * thats another option.
2468               */
2469              if (!child->iconic)
2470                {
2471                   if (last)
2472                     e_border_stack_below(child, last);
2473                   else
2474                     {
2475                        E_Border *below;
2476
2477                        /* First lower the border to find out which border we will end up below */
2478                        below = e_container_border_lower(child);
2479
2480                        if (below)
2481                          {
2482                             /* We ended up below a border, now we must stack this border to
2483                              * generate the stacking event, and to check if this transient
2484                              * has other transients etc.
2485                              */
2486                             e_border_stack_below(child, below);
2487                          }
2488                        else
2489                          {
2490                             /* If we didn't end up below any border, we are on top! */
2491                             e_border_raise(child);
2492                          }
2493                     }
2494                   last = child;
2495                }
2496           }
2497         eina_list_free(list);
2498
2499 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2500           }
2501         else
2502           {
2503              EINA_LIST_FOREACH(bd->transients, l, child)
2504                {
2505                 /* Don't stack iconic transients. If the user wants these shown,
2506                  * thats another option.
2507                  */
2508                   if (!child->iconic)
2509                     {
2510                        child->layer = bd->layer;
2511                        e_border_lower (child);
2512                        last = child;
2513                     }
2514                }
2515           }
2516 #endif
2517      }
2518
2519    ev = E_NEW(E_Event_Border_Stack, 1);
2520    ev->border = bd;
2521    e_object_ref(E_OBJECT(bd));
2522
2523    if (last)
2524      {
2525         e_container_border_stack_below(bd, last);
2526         ev->stack = last;
2527         e_object_ref(E_OBJECT(last));
2528         ev->type = E_STACKING_BELOW;
2529      }
2530    else
2531      {
2532         E_Border *below;
2533
2534         /* If we don't have any children, lower this border */
2535         below = e_container_border_lower(bd);
2536         if (below)
2537           {
2538              /* We ended up below a border */
2539               ev->stack = below;
2540               e_object_ref(E_OBJECT(below));
2541               ev->type = E_STACKING_BELOW;
2542           }
2543         else
2544           {
2545              /* No border to hide under, same as a raise! */
2546               ev->stack = NULL;
2547               ev->type = E_STACKING_BELOW;
2548           }
2549      }
2550
2551    ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2552    e_remember_update(bd);
2553 }
2554
2555 EAPI void
2556 e_border_stack_above(E_Border *bd,
2557                      E_Border *above)
2558 {
2559    /* TODO: Should stack above allow the border to change level */
2560     E_Event_Border_Stack *ev;
2561     E_Border *last = NULL, *child;
2562     Eina_List *l;
2563
2564     E_OBJECT_CHECK(bd);
2565     E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2566
2567     ecore_x_window_shadow_tree_flush();
2568
2569     if (e_config->transient.raise)
2570       {
2571          Eina_List *list = _e_border_sub_borders_new(bd);
2572
2573          EINA_LIST_REVERSE_FOREACH(list, l, child)
2574            {
2575               /* Don't stack iconic transients. If the user wants these shown,
2576                * thats another option.
2577                */
2578               if (!child->iconic)
2579                 {
2580                    if (last)
2581                      e_border_stack_below(child, last);
2582                    else
2583                      e_border_stack_above(child, above);
2584                    last = child;
2585                 }
2586            }
2587          eina_list_free(list);
2588       }
2589
2590     ev = E_NEW(E_Event_Border_Stack, 1);
2591     ev->border = bd;
2592     e_object_ref(E_OBJECT(bd));
2593
2594     if (last)
2595       {
2596          e_container_border_stack_below(bd, last);
2597          ev->stack = last;
2598          e_object_ref(E_OBJECT(last));
2599          ev->type = E_STACKING_BELOW;
2600       }
2601     else
2602       {
2603          e_container_border_stack_above(bd, above);
2604          ev->stack = above;
2605          e_object_ref(E_OBJECT(above));
2606          ev->type = E_STACKING_ABOVE;
2607       }
2608
2609     ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2610     e_remember_update(bd);
2611 }
2612
2613 EAPI void
2614 e_border_stack_below(E_Border *bd,
2615                      E_Border *below)
2616 {
2617    /* TODO: Should stack below allow the border to change level */
2618     E_Event_Border_Stack *ev;
2619     E_Border *last = NULL, *child;
2620     Eina_List *l;
2621
2622     E_OBJECT_CHECK(bd);
2623     E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2624
2625     ecore_x_window_shadow_tree_flush();
2626
2627     if (e_config->transient.lower)
2628       {
2629          Eina_List *list = _e_border_sub_borders_new(bd);
2630
2631          EINA_LIST_REVERSE_FOREACH(bd->transients, l, child)
2632            {
2633               /* Don't stack iconic transients. If the user wants these shown,
2634                * thats another option.
2635                */
2636               if (!child->iconic)
2637                 {
2638                    if (last)
2639                      e_border_stack_below(child, last);
2640                    else
2641                      e_border_stack_below(child, below);
2642                    last = child;
2643                 }
2644            }
2645          eina_list_free(list);
2646       }
2647
2648     ev = E_NEW(E_Event_Border_Stack, 1);
2649     ev->border = bd;
2650     e_object_ref(E_OBJECT(bd));
2651
2652     if (last)
2653       {
2654          e_container_border_stack_below(bd, last);
2655          ev->stack = last;
2656          e_object_ref(E_OBJECT(last));
2657          ev->type = E_STACKING_BELOW;
2658       }
2659     else
2660       {
2661          e_container_border_stack_below(bd, below);
2662          ev->stack = below;
2663          e_object_ref(E_OBJECT(below));
2664          ev->type = E_STACKING_BELOW;
2665       }
2666
2667     ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2668     e_remember_update(bd);
2669 }
2670
2671 EAPI void
2672 e_border_focus_latest_set(E_Border *bd)
2673 {
2674    focus_stack = eina_list_remove(focus_stack, bd);
2675    focus_stack = eina_list_prepend(focus_stack, bd);
2676 }
2677
2678 EAPI void
2679 e_border_raise_latest_set(E_Border *bd)
2680 {
2681    raise_stack = eina_list_remove(raise_stack, bd);
2682    raise_stack = eina_list_prepend(raise_stack, bd);
2683 }
2684
2685 /*
2686  * Sets the focus to the given border if necessary
2687  * There are 3 cases of different focus_policy-configurations:
2688  *
2689  * - E_FOCUS_CLICK: just set the focus, the most simple one
2690  *
2691  * - E_FOCUS_MOUSE: focus is where the mouse is, so try to
2692  *   warp the pointer to the window. If this fails (because
2693  *   the pointer is already in the window), just set the focus.
2694  *
2695  * - E_FOCUS_SLOPPY: focus is where the mouse is or on the
2696  *   last window which was focused, if the mouse is on the
2697  *   desktop. So, we need to look if there is another window
2698  *   under the pointer and warp to pointer to the right
2699  *   one if so (also, we set the focus afterwards). In case
2700  *   there is no window under pointer, the pointer is on the
2701  *   desktop and so we just set the focus.
2702  *
2703  *
2704  * This function is to be called when setting the focus was not
2705  * explicitly triggered by the user (by moving the mouse or
2706  * clicking for example), but implicitly (by closing a window,
2707  * the last focused window should get focus).
2708  *
2709  */
2710 EAPI void
2711 e_border_focus_set_with_pointer(E_Border *bd)
2712 {
2713 #ifdef PRINT_LOTS_OF_DEBUG
2714    E_PRINT_BORDER_INFO(bd);
2715 #endif
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)) return;
2722    if (bd->lock_focus_out) return;
2723
2724    e_border_focus_set(bd, 1, 1);
2725
2726    if (e_config->focus_policy == E_FOCUS_CLICK) return;
2727    if (!bd->visible) return;
2728
2729    if (e_config->focus_policy == E_FOCUS_SLOPPY)
2730      {
2731         if (!e_border_under_pointer_get(bd->desk, bd))
2732           {
2733              e_border_pointer_warp_to_center(bd);
2734           }
2735      }
2736    else
2737      {
2738         e_border_pointer_warp_to_center(bd);
2739      }
2740 }
2741
2742 EAPI void
2743 e_border_focus_set(E_Border *bd,
2744                    int       focus,
2745                    int       set)
2746 {
2747    E_Border *bd_unfocus = NULL;
2748    Eina_Bool focus_changed = EINA_FALSE;
2749
2750    E_OBJECT_CHECK(bd);
2751    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2752    /* note: this is here as it seems there are enough apps that do not even
2753     * expect us to emulate a look of focus but not actually set x input
2754     * focus as we do - so simply abort any focuse set on such windows */
2755    /* be strict about accepting focus hint */
2756    if ((!bd->client.icccm.accepts_focus) &&
2757        (!bd->client.icccm.take_focus))
2758      return;
2759    if ((set) && (focus) && (bd->lock_focus_out)) return;
2760    
2761    /* dont focus an iconified window. that's silly! */
2762    if (focus)
2763      {
2764         if (bd->iconic)
2765           {
2766              e_border_uniconify(bd);
2767              if (!focus_track_frozen)
2768                e_border_focus_latest_set(bd);
2769              return;
2770           }
2771         else if (!bd->visible)
2772           {
2773              return;
2774           }
2775         /* FIXME: hack for deskflip animation:
2776          * dont update focus when sliding previous desk */
2777         else if ((!bd->sticky) &&
2778                  (bd->desk != e_desk_current_get(bd->desk->zone)))
2779           {
2780              return;
2781           }
2782      }
2783
2784    if ((bd->modal) && (bd->modal != bd) && (bd->modal->visible))
2785      {
2786         e_border_focus_set(bd->modal, focus, set);
2787         return;
2788      }
2789    else if ((bd->leader) && (bd->leader->modal) && (bd->leader->modal != bd))
2790      {
2791         e_border_focus_set(bd->leader->modal, focus, set);
2792         return;
2793      }
2794
2795    if (focus)
2796      {
2797         if (set)
2798           {
2799              if (bd->visible && bd->changes.visible)
2800                {
2801                   bd->want_focus = 1;
2802                   bd->changed = 1;
2803                }
2804              else if ((!bd->focused) ||
2805                       (focus_next && (bd != eina_list_data_get(focus_next))))
2806                {
2807                   Eina_List *l;
2808
2809                   if ((l = eina_list_data_find_list(focus_next, bd)))
2810                     focus_next = eina_list_promote_list(focus_next, l);
2811                   else
2812                     focus_next = eina_list_prepend(focus_next, bd);
2813                }
2814              if ((bd->client.icccm.take_focus) &&
2815                  (bd->client.icccm.accepts_focus))
2816                {
2817                   e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
2818                   /* TODO what if the client didn't take focus ? */
2819                }
2820              else if (!bd->client.icccm.accepts_focus)
2821                {
2822                   e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
2823                }
2824              else if (!bd->client.icccm.take_focus)
2825                {
2826                   e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
2827                   /* e_border_focus_set(bd, 1, 0); */
2828                }
2829             return;
2830           }
2831
2832         if (!bd->focused)
2833           {
2834              Eina_List *l;
2835              E_Border *bd2;
2836              
2837              if (focused) bd_unfocus = focused;
2838              if (focusing == bd) focusing = NULL;
2839              bd->focused = 1;
2840              focused = bd;
2841              if (!bd_unfocus)
2842                {
2843                   EINA_LIST_FOREACH(e_border_client_list(), l, bd2)
2844                     {
2845                        if ((bd2->fullscreen) &&
2846                            (bd2 != bd) &&
2847                            (bd2->zone == bd->zone) &&
2848                            ((bd2->desk == bd->desk) ||
2849                                (bd2->sticky) || (bd->sticky)))
2850                          {
2851                             Eina_Bool unfocus_is_parent = EINA_FALSE;
2852                             E_Border *bd_parent;
2853                             
2854                             bd_parent = bd->parent;
2855                             while (bd_parent)
2856                               {
2857                                  if (bd_parent == bd2)
2858                                    {
2859                                       unfocus_is_parent = EINA_TRUE;
2860                                       break;
2861                                    }
2862                                  bd_parent = bd->parent;
2863                               }
2864                             if ((!unfocus_is_parent) && 
2865                                 (!e_config->allow_above_fullscreen))
2866                               {
2867                                  e_border_iconify(bd2);
2868                               }
2869                          }
2870                     }
2871                }
2872              focus_changed = EINA_TRUE;
2873           }
2874      }
2875    else
2876      {
2877         bd->want_focus = 0;
2878         focus_next = eina_list_remove(focus_next, bd);
2879         if (bd == focusing) focusing = NULL;
2880
2881         if ((bd->focused) && 
2882             ((bd->desk == e_desk_current_get(bd->zone)) || (bd->sticky)))
2883           {
2884              Eina_Bool wasfocused = EINA_FALSE;
2885              bd_unfocus = bd;
2886
2887              /* should always be the case. anyway */
2888              if (bd == focused)
2889                {
2890                   focused = NULL;
2891                   wasfocused = EINA_TRUE;
2892                }
2893
2894              if ((set) && (!focus_next) && (!focusing))
2895                {
2896                   e_grabinput_focus(bd->zone->container->bg_win,
2897                                     E_FOCUS_METHOD_PASSIVE);
2898                }
2899              if ((bd->fullscreen) && (wasfocused))
2900                {
2901                   Eina_Bool have_vis_child = EINA_FALSE;
2902                   Eina_List *l;
2903                   E_Border *bd2;
2904                   
2905                   EINA_LIST_FOREACH(e_border_client_list(), l, bd2)
2906                     {
2907                        if ((bd2 != bd) &&
2908                            (bd2->zone == bd->zone) &&
2909                            ((bd2->desk == bd->desk) ||
2910                                (bd2->sticky) || (bd->sticky)))
2911                          {
2912                             if (bd2->parent == bd)
2913                               {
2914                                  have_vis_child = EINA_TRUE;
2915                                  break;
2916                               }
2917                          }
2918                     }
2919                   if ((!have_vis_child) && 
2920                       (!e_config->allow_above_fullscreen))
2921                     e_border_iconify(bd);
2922                }
2923           }
2924      }
2925    
2926    if ((bd_unfocus) &&
2927        (!e_object_is_del(E_OBJECT(bd_unfocus)) &&
2928         (e_object_ref_get(E_OBJECT(bd_unfocus)) > 0)))
2929      {
2930         E_Event_Border_Focus_Out *ev;
2931
2932         bd_unfocus->focused = 0;
2933         e_focus_event_focus_out(bd_unfocus);
2934
2935         if (bd_unfocus->raise_timer)
2936           ecore_timer_del(bd_unfocus->raise_timer);
2937         bd_unfocus->raise_timer = NULL;
2938
2939         edje_object_signal_emit(bd_unfocus->bg_object, "e,state,unfocused", "e");
2940         if (bd_unfocus->icon_object)
2941           edje_object_signal_emit(bd_unfocus->icon_object, "e,state,unfocused", "e");
2942
2943         ev = E_NEW(E_Event_Border_Focus_Out, 1);
2944         ev->border = bd_unfocus;
2945         e_object_ref(E_OBJECT(bd_unfocus));
2946
2947         ecore_event_add(E_EVENT_BORDER_FOCUS_OUT, ev,
2948                         _e_border_event_border_focus_out_free, NULL);
2949         if ((bd_unfocus->fullscreen) &&
2950             (bd != bd_unfocus) &&
2951             (bd->zone == bd_unfocus->zone) &&
2952             ((bd->desk == bd_unfocus->desk) ||
2953              (bd->sticky) || (bd_unfocus->sticky)))
2954           {
2955              Eina_Bool unfocus_is_parent = EINA_FALSE;
2956              E_Border *bd_parent;
2957
2958              bd_parent = bd->parent;
2959              while (bd_parent)
2960                {
2961                   if (bd_parent == bd_unfocus)
2962                     {
2963                        unfocus_is_parent = EINA_TRUE;
2964                        break;
2965                     }
2966                   bd_parent = bd->parent;
2967                }
2968              if ((!unfocus_is_parent) && (!e_config->allow_above_fullscreen))
2969                {
2970                   e_border_iconify(bd_unfocus);
2971                }
2972           }
2973      }
2974
2975    if (focus_changed)
2976      {
2977         E_Event_Border_Focus_In *ev;
2978
2979         e_focus_event_focus_in(bd);
2980
2981         if (!focus_track_frozen)
2982           e_border_focus_latest_set(bd);
2983
2984         e_hints_active_window_set(bd->zone->container->manager, bd);
2985
2986         edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
2987         if (bd->icon_object)
2988           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
2989
2990         ev = E_NEW(E_Event_Border_Focus_In, 1);
2991         ev->border = bd;
2992         e_object_ref(E_OBJECT(bd));
2993
2994         ecore_event_add(E_EVENT_BORDER_FOCUS_IN, ev,
2995                         _e_border_event_border_focus_in_free, NULL);
2996      }
2997 }
2998
2999 EAPI void
3000 e_border_shade(E_Border   *bd,
3001                E_Direction dir)
3002 {
3003    E_Event_Border_Resize *ev;
3004    Eina_List *l;
3005    E_Border *tmp;
3006
3007    E_OBJECT_CHECK(bd);
3008    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3009    if ((bd->shaded) || (bd->shading) || (bd->fullscreen) ||
3010        ((bd->maximized) && (!e_config->allow_manip))) return;
3011    if ((bd->client.border.name) &&
3012        (!strcmp("borderless", bd->client.border.name))) return;
3013
3014    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
3015      ecore_x_window_hide(tmp->win);
3016
3017    ecore_x_window_shadow_tree_flush();
3018
3019    bd->shade.x = bd->x;
3020    bd->shade.y = bd->y;
3021    bd->shade.dir = dir;
3022
3023    e_hints_window_shaded_set(bd, 1);
3024    e_hints_window_shade_direction_set(bd, dir);
3025
3026    if (e_config->border_shade_animate)
3027      {
3028         bd->shade.start = ecore_loop_time_get();
3029         bd->shading = 1;
3030         bd->changes.shading = 1;
3031         bd->changed = 1;
3032
3033         if (bd->shade.dir == E_DIRECTION_UP ||
3034             bd->shade.dir == E_DIRECTION_LEFT)
3035           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
3036         else
3037           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NE);
3038
3039         bd->shade.anim = ecore_animator_add(_e_border_shade_animator, bd);
3040         edje_object_signal_emit(bd->bg_object, "e,state,shading", "e");
3041      }
3042    else
3043      {
3044         if (bd->shade.dir == E_DIRECTION_UP)
3045           {
3046              bd->h = bd->client_inset.t + bd->client_inset.b;
3047           }
3048         else if (bd->shade.dir == E_DIRECTION_DOWN)
3049           {
3050              bd->h = bd->client_inset.t + bd->client_inset.b;
3051              bd->y = bd->y + bd->client.h;
3052              bd->changes.pos = 1;
3053           }
3054         else if (bd->shade.dir == E_DIRECTION_LEFT)
3055           {
3056              bd->w = bd->client_inset.l + bd->client_inset.r;
3057           }
3058         else if (bd->shade.dir == E_DIRECTION_RIGHT)
3059           {
3060              bd->w = bd->client_inset.l + bd->client_inset.r;
3061              bd->x = bd->x + bd->client.w;
3062              bd->changes.pos = 1;
3063           }
3064
3065         if ((bd->shaped) || (bd->client.shaped))
3066           {
3067              bd->need_shape_merge = 1;
3068              bd->need_shape_export = 1;
3069           }
3070         if (bd->shaped_input)
3071           {
3072              bd->need_shape_merge = 1;
3073           }
3074
3075         bd->changes.size = 1;
3076         bd->shaded = 1;
3077         bd->changes.shaded = 1;
3078         bd->changed = 1;
3079         edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
3080         e_border_frame_recalc(bd);
3081         ev = E_NEW(E_Event_Border_Resize, 1);
3082         ev->border = bd;
3083         /* The resize is added in the animator when animation complete */
3084         /* For non-animated, we add it immediately with the new size */
3085         e_object_ref(E_OBJECT(bd));
3086         //           e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
3087         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
3088      }
3089
3090    e_remember_update(bd);
3091 }
3092
3093 EAPI void
3094 e_border_unshade(E_Border   *bd,
3095                  E_Direction dir)
3096 {
3097    E_Event_Border_Resize *ev;
3098    Eina_List *l;
3099    E_Border *tmp;
3100
3101    E_OBJECT_CHECK(bd);
3102    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3103    if ((!bd->shaded) || (bd->shading))
3104      return;
3105
3106    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
3107      ecore_x_window_show(tmp->win);
3108
3109    ecore_x_window_shadow_tree_flush();
3110
3111    bd->shade.dir = dir;
3112
3113    e_hints_window_shaded_set(bd, 0);
3114    e_hints_window_shade_direction_set(bd, dir);
3115
3116    if (bd->shade.dir == E_DIRECTION_UP ||
3117        bd->shade.dir == E_DIRECTION_LEFT)
3118      {
3119         bd->shade.x = bd->x;
3120         bd->shade.y = bd->y;
3121      }
3122    else
3123      {
3124         bd->shade.x = bd->x - bd->client.w;
3125         bd->shade.y = bd->y - bd->client.h;
3126      }
3127    if (e_config->border_shade_animate)
3128      {
3129         bd->shade.start = ecore_loop_time_get();
3130         bd->shading = 1;
3131         bd->changes.shading = 1;
3132         bd->changed = 1;
3133
3134         if (bd->shade.dir == E_DIRECTION_UP)
3135           {
3136              ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
3137              ecore_x_window_move_resize(bd->client.win, 0,
3138                                         bd->h - (bd->client_inset.t + bd->client_inset.b) -
3139                                         bd->client.h,
3140                                         bd->client.w, bd->client.h);
3141           }
3142         else if (bd->shade.dir == E_DIRECTION_LEFT)
3143           {
3144              ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
3145              ecore_x_window_move_resize(bd->client.win,
3146                                         bd->w - (bd->client_inset.l + bd->client_inset.r) -
3147                                         bd->client.h,
3148                                         0, bd->client.w, bd->client.h);
3149           }
3150         else
3151           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NE);
3152
3153         bd->shade.anim = ecore_animator_add(_e_border_shade_animator, bd);
3154         edje_object_signal_emit(bd->bg_object, "e,state,unshading", "e");
3155      }
3156    else
3157      {
3158         if (bd->shade.dir == E_DIRECTION_UP)
3159           {
3160              bd->h = bd->client_inset.t + bd->client.h + bd->client_inset.b;
3161           }
3162         else if (bd->shade.dir == E_DIRECTION_DOWN)
3163           {
3164              bd->h = bd->client_inset.t + bd->client.h + bd->client_inset.b;
3165              bd->y = bd->y - bd->client.h;
3166              bd->changes.pos = 1;
3167           }
3168         else if (bd->shade.dir == E_DIRECTION_LEFT)
3169           {
3170              bd->w = bd->client_inset.l + bd->client.w + bd->client_inset.r;
3171           }
3172         else if (bd->shade.dir == E_DIRECTION_RIGHT)
3173           {
3174              bd->w = bd->client_inset.l + bd->client.w + bd->client_inset.r;
3175              bd->x = bd->x - bd->client.w;
3176              bd->changes.pos = 1;
3177           }
3178         if ((bd->shaped) || (bd->client.shaped))
3179           {
3180              bd->need_shape_merge = 1;
3181              bd->need_shape_export = 1;
3182           }
3183         if (bd->shaped_input)
3184           {
3185              bd->need_shape_merge = 1;
3186           }
3187
3188         bd->changes.size = 1;
3189         bd->shaded = 0;
3190         bd->changes.shaded = 1;
3191         bd->changed = 1;
3192         edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
3193         e_border_frame_recalc(bd);
3194         ev = E_NEW(E_Event_Border_Resize, 1);
3195         ev->border = bd;
3196         /* The resize is added in the animator when animation complete */
3197         /* For non-animated, we add it immediately with the new size */
3198         e_object_ref(E_OBJECT(bd));
3199         //           e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
3200         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
3201      }
3202
3203    e_remember_update(bd);
3204 }
3205
3206 static void
3207 _e_border_client_inset_calc(E_Border *bd)
3208 {
3209    /* int w, h; */
3210    Evas_Coord cx, cy, cw, ch;
3211
3212    if (bd->bg_object)
3213      {
3214         evas_object_resize(bd->bg_object, 1000, 1000);
3215         edje_object_message_signal_process(bd->bg_object);
3216         edje_object_calc_force(bd->bg_object);
3217         edje_object_part_geometry_get(bd->bg_object, "e.swallow.client", &cx, &cy, &cw, &ch);
3218         bd->client_inset.l = cx;
3219         bd->client_inset.r = 1000 - (cx + cw);
3220         bd->client_inset.t = cy;
3221         bd->client_inset.b = 1000 - (cy + ch);
3222      }
3223    else
3224      {
3225         bd->client_inset.l = 0;
3226         bd->client_inset.r = 0;
3227         bd->client_inset.t = 0;
3228         bd->client_inset.b = 0;
3229      }
3230
3231    ecore_x_netwm_frame_size_set(bd->client.win,
3232                                 bd->client_inset.l, bd->client_inset.r,
3233                                 bd->client_inset.t, bd->client_inset.b);
3234    ecore_x_e_frame_size_set(bd->client.win,
3235                             bd->client_inset.l, bd->client_inset.r,
3236                             bd->client_inset.t, bd->client_inset.b);
3237 }
3238
3239 static void
3240 _e_border_maximize(E_Border *bd, E_Maximize max)
3241 {
3242    int x1, yy1, x2, y2;
3243    int w, h, pw, ph;
3244    int zx, zy, zw, zh;
3245 #ifdef _F_USE_BOTTOM_TOP_MAXIMIZE
3246    int cy = 0;
3247 #endif
3248
3249    zx = zy = zw = zh = 0;
3250
3251    switch (max & E_MAXIMIZE_TYPE)
3252      {
3253       case E_MAXIMIZE_NONE:
3254          /* Ignore */
3255          break;
3256
3257       case E_MAXIMIZE_FULLSCREEN:
3258          w = bd->zone->w;
3259          h = bd->zone->h;
3260
3261          if (bd->bg_object)
3262            {
3263               edje_object_signal_emit(bd->bg_object, "e,action,maximize,fullscreen", "e");
3264               _e_border_client_inset_calc(bd);
3265            }
3266          e_border_resize_limit(bd, &w, &h);
3267          /* center x-direction */
3268          x1 = bd->zone->x + (bd->zone->w - w) / 2;
3269          /* center y-direction */
3270          yy1 = bd->zone->y + (bd->zone->h - h) / 2;
3271
3272 #ifdef _F_USE_BOTTOM_TOP_MAXIMIZE
3273          cy = bd->zone->y + (bd->zone->h / 2);
3274 #endif
3275
3276          switch (max & E_MAXIMIZE_DIRECTION)
3277            {
3278             case E_MAXIMIZE_BOTH:
3279               e_border_move_resize(bd, x1, yy1, w, h);
3280               break;
3281
3282             case E_MAXIMIZE_VERTICAL:
3283               e_border_move_resize(bd, bd->x, yy1, bd->w, h);
3284               break;
3285
3286             case E_MAXIMIZE_HORIZONTAL:
3287               e_border_move_resize(bd, x1, bd->y, w, bd->h);
3288               break;
3289
3290             case E_MAXIMIZE_LEFT:
3291               e_border_move_resize(bd, bd->zone->x, bd->zone->y, w / 2, h);
3292               break;
3293
3294             case E_MAXIMIZE_RIGHT:
3295               e_border_move_resize(bd, x1, bd->zone->y, w / 2, h);
3296               break;
3297 #ifdef _F_USE_BOTTOM_TOP_MAXIMIZE
3298             case E_MAXIMIZE_TOP:
3299               e_border_move_resize(bd, bd->zone->x, bd->zone->y, w, h / 2);
3300               break;
3301             case E_MAXIMIZE_BOTTOM:
3302               e_border_move_resize(bd, bd->zone->x, cy, w, h / 2);
3303               break;
3304 #endif
3305            }
3306          break;
3307
3308       case E_MAXIMIZE_SMART:
3309       case E_MAXIMIZE_EXPAND:
3310          if (bd->zone)
3311            e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
3312
3313          if (bd->w < zw)
3314            w = bd->w;
3315          else
3316            w = zw;
3317
3318          if (bd->h < zh)
3319            h = bd->h;
3320          else
3321            h = zh;
3322
3323          if (bd->x < zx) // window left not useful coordinates
3324            x1 = zx;
3325          else if (bd->x + bd->w > zx + zw) // window right not useful coordinates
3326            x1 = zx + zw - bd->w;
3327          else // window normal position
3328            x1 = bd->x;
3329
3330          if (bd->y < zy) // window top not useful coordinates
3331            yy1 = zy;
3332          else if (bd->y + bd->h > zy + zh) // window bottom not useful coordinates
3333            yy1 = zy + zh - bd->h;
3334          else // window normal position
3335            yy1 = bd->y;
3336
3337          switch (max & E_MAXIMIZE_DIRECTION)
3338            {
3339             case E_MAXIMIZE_BOTH:
3340               e_border_move_resize(bd, zx, zy, zw, zh);
3341               break;
3342
3343             case E_MAXIMIZE_VERTICAL:
3344               e_border_move_resize(bd, x1, zy, w, zh);
3345               break;
3346
3347             case E_MAXIMIZE_HORIZONTAL:
3348               e_border_move_resize(bd, zx, yy1, zw, h);
3349               break;
3350
3351             case E_MAXIMIZE_LEFT:
3352               e_border_move_resize(bd, zx, zy, zw / 2, zh);
3353               break;
3354
3355             case E_MAXIMIZE_RIGHT:
3356               e_border_move_resize(bd, zx + zw / 2, zy, zw / 2, zh);
3357               break;
3358            }
3359
3360          edje_object_signal_emit(bd->bg_object, "e,action,maximize", "e");
3361          break;
3362
3363       case E_MAXIMIZE_FILL:
3364          x1 = bd->zone->x;
3365          yy1 = bd->zone->y;
3366          x2 = bd->zone->x + bd->zone->w;
3367          y2 = bd->zone->y + bd->zone->h;
3368
3369          /* walk through all shelves */
3370          e_maximize_border_shelf_fill(bd, &x1, &yy1, &x2, &y2, max);
3371
3372          /* walk through all windows */
3373          e_maximize_border_border_fill(bd, &x1, &yy1, &x2, &y2, max);
3374
3375          w = x2 - x1;
3376          h = y2 - yy1;
3377          pw = w;
3378          ph = h;
3379          e_border_resize_limit(bd, &w, &h);
3380          /* center x-direction */
3381          x1 = x1 + (pw - w) / 2;
3382          /* center y-direction */
3383          yy1 = yy1 + (ph - h) / 2;
3384
3385          switch (max & E_MAXIMIZE_DIRECTION)
3386            {
3387             case E_MAXIMIZE_BOTH:
3388               e_border_move_resize(bd, x1, yy1, w, h);
3389               break;
3390
3391             case E_MAXIMIZE_VERTICAL:
3392               e_border_move_resize(bd, bd->x, yy1, bd->w, h);
3393               break;
3394
3395             case E_MAXIMIZE_HORIZONTAL:
3396               e_border_move_resize(bd, x1, bd->y, w, bd->h);
3397               break;
3398
3399             case E_MAXIMIZE_LEFT:
3400               e_border_move_resize(bd, bd->zone->x, bd->zone->y, w / 2, h);
3401               break;
3402
3403             case E_MAXIMIZE_RIGHT:
3404               e_border_move_resize(bd, x1, bd->zone->y, w / 2, h);
3405               break;
3406            }
3407          break;
3408      }
3409 }
3410
3411 EAPI void
3412 e_border_maximize(E_Border  *bd,
3413                   E_Maximize max)
3414 {
3415    E_OBJECT_CHECK(bd);
3416    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3417
3418    if (!(max & E_MAXIMIZE_DIRECTION)) max |= E_MAXIMIZE_BOTH;
3419
3420    if ((bd->shaded) || (bd->shading)) return;
3421    ecore_x_window_shadow_tree_flush();
3422    if (bd->fullscreen)
3423      e_border_unfullscreen(bd);
3424    /* Only allow changes in vertical/ horizontal maximization */
3425    if (((bd->maximized & E_MAXIMIZE_DIRECTION) == (max & E_MAXIMIZE_DIRECTION)) ||
3426        ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
3427    if (bd->new_client)
3428      {
3429         bd->need_maximize = 1;
3430         bd->maximized &= ~E_MAXIMIZE_TYPE;
3431         bd->maximized |= max;
3432         return;
3433      }
3434
3435    bd->pre_res_change.valid = 0;
3436    if (!(bd->maximized & E_MAXIMIZE_HORIZONTAL))
3437      {
3438         /* Horizontal hasn't been set */
3439         bd->saved.x = bd->x - bd->zone->x;
3440         bd->saved.w = bd->w;
3441      }
3442    if (!(bd->maximized & E_MAXIMIZE_VERTICAL))
3443      {
3444         /* Vertical hasn't been set */
3445         bd->saved.y = bd->y - bd->zone->y;
3446         bd->saved.h = bd->h;
3447      }
3448
3449    bd->saved.zone = bd->zone->num;
3450    e_hints_window_size_set(bd);
3451
3452    e_border_raise(bd);
3453
3454    _e_border_maximize(bd, max);
3455
3456
3457    /* Remove previous type */
3458    bd->maximized &= ~E_MAXIMIZE_TYPE;
3459    /* Add new maximization. It must be added, so that VERTICAL + HORIZONTAL == BOTH */
3460    bd->maximized |= max;
3461
3462    e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
3463                                 bd->maximized & E_MAXIMIZE_VERTICAL);
3464    e_remember_update(bd);
3465 }
3466
3467 EAPI void
3468 e_border_unmaximize(E_Border  *bd,
3469                     E_Maximize max)
3470 {
3471    E_OBJECT_CHECK(bd);
3472    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3473    if (!(max & E_MAXIMIZE_DIRECTION))
3474      {
3475         CRI("BUG: Unmaximize call without direction!");
3476         return;
3477      }
3478
3479    if ((bd->shaded) || (bd->shading)) return;
3480    ecore_x_window_shadow_tree_flush();
3481    /* Remove directions not used */
3482    max &= (bd->maximized & E_MAXIMIZE_DIRECTION);
3483    /* Can only remove existing maximization directions */
3484    if (!max) return;
3485    if (bd->maximized & E_MAXIMIZE_TYPE)
3486      {
3487         bd->pre_res_change.valid = 0;
3488         bd->need_maximize = 0;
3489
3490         if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN)
3491           {
3492              if (bd->bg_object)
3493                {
3494                   edje_object_signal_emit(bd->bg_object, "e,action,unmaximize,fullscreen", "e");
3495                   _e_border_client_inset_calc(bd);
3496                }
3497
3498              bd->maximized = E_MAXIMIZE_NONE;
3499              _e_border_move_resize_internal(bd,
3500                                             bd->zone->x + bd->saved.x,
3501                                             bd->zone->y + bd->saved.y,
3502                                             bd->saved.w, bd->saved.h, 0, 1);
3503              bd->saved.x = bd->saved.y = bd->saved.w = bd->saved.h = 0;
3504              e_hints_window_size_unset(bd);
3505           }
3506         else
3507           {
3508              int w, h, x, y;
3509
3510              w = bd->w;
3511              h = bd->h;
3512              x = bd->x;
3513              y = bd->y;
3514
3515              if (max & E_MAXIMIZE_VERTICAL)
3516                {
3517                   /* Remove vertical */
3518                   h = bd->saved.h;
3519                   y = bd->saved.y + bd->zone->y;
3520                   bd->saved.h = bd->saved.y = 0;
3521                   bd->maximized &= ~E_MAXIMIZE_VERTICAL;
3522                   bd->maximized &= ~E_MAXIMIZE_LEFT;
3523                   bd->maximized &= ~E_MAXIMIZE_RIGHT;
3524                }
3525              if (max & E_MAXIMIZE_HORIZONTAL)
3526                {
3527                   /* Remove horizontal */
3528                   w = bd->saved.w;
3529                   x = bd->saved.x + bd->zone->x;
3530                   bd->saved.w = bd->saved.x = 0;
3531                   bd->maximized &= ~E_MAXIMIZE_HORIZONTAL;
3532                }
3533
3534              e_border_resize_limit(bd, &w, &h);
3535
3536              if (!(bd->maximized & E_MAXIMIZE_DIRECTION))
3537                {
3538                   bd->maximized = E_MAXIMIZE_NONE;
3539                   _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
3540                   e_hints_window_size_unset(bd);
3541                   edje_object_signal_emit(bd->bg_object, "e,action,unmaximize", "e");
3542                }
3543              else
3544                {
3545                   _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
3546                   e_hints_window_size_set(bd);
3547                }
3548           }
3549         e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
3550                                      bd->maximized & E_MAXIMIZE_VERTICAL);
3551      }
3552    e_remember_update(bd);
3553 }
3554
3555 EAPI void
3556 e_border_fullscreen(E_Border    *bd,
3557                     E_Fullscreen policy)
3558 {
3559    E_Event_Border_Fullscreen *ev;
3560
3561    E_OBJECT_CHECK(bd);
3562    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3563
3564    if ((bd->shaded) || (bd->shading)) return;
3565    ecore_x_window_shadow_tree_flush();
3566    if (bd->new_client)
3567      {
3568         bd->need_fullscreen = 1;
3569         return;
3570      }
3571    if (!bd->fullscreen)
3572      {
3573         bd->pre_res_change.valid = 0;
3574
3575         bd->saved.x = bd->x - bd->zone->x;
3576         bd->saved.y = bd->y - bd->zone->y;
3577         bd->saved.w = bd->client.w;
3578         bd->saved.h = bd->client.h;
3579         bd->saved.maximized = bd->maximized;
3580         bd->saved.zone = bd->zone->num;
3581
3582         if (bd->maximized)
3583           e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
3584         e_hints_window_size_set(bd);
3585
3586         bd->client_inset.l = 0;
3587         bd->client_inset.r = 0;
3588         bd->client_inset.t = 0;
3589         bd->client_inset.b = 0;
3590
3591         bd->desk->fullscreen_borders++;
3592
3593         /* e_zone_fullscreen_set(bd->zone, 1); */
3594         bd->saved.layer = bd->layer;
3595         if (!e_config->allow_above_fullscreen)
3596           e_border_layer_set(bd, 250);
3597
3598         if ((eina_list_count(bd->zone->container->zones) > 1) ||
3599             (policy == E_FULLSCREEN_RESIZE) || (!ecore_x_randr_query()))
3600           {
3601              e_border_move_resize(bd, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h);
3602           }
3603         else if (policy == E_FULLSCREEN_ZOOM)
3604           {
3605              Ecore_X_Randr_Screen_Size_MM *sizes;
3606              int num_sizes, i, best_size_index = 0;
3607
3608              ecore_x_randr_screen_primary_output_current_size_get(bd->zone->container->manager->root,
3609                                                                   &screen_size.width,
3610                                                                   &screen_size.height,
3611                                                                   NULL, NULL, NULL);
3612              sizes = ecore_x_randr_screen_primary_output_sizes_get(bd->zone->container->manager->root,
3613                                                                    &num_sizes);
3614              if (sizes)
3615                {
3616                   Ecore_X_Randr_Screen_Size best_size = { -1, -1 };
3617                   int best_dist = INT_MAX, dist;
3618
3619                   for (i = 0; i < num_sizes; i++)
3620                     {
3621                        if ((sizes[i].width > bd->w) && (sizes[i].height > bd->h))
3622                          {
3623                             dist = (sizes[i].width * sizes[i].height) - (bd->w * bd->h);
3624                             if (dist < best_dist)
3625                               {
3626                                  best_size.width = sizes[i].width;
3627                                  best_size.height = sizes[i].height;
3628                                  best_dist = dist;
3629                                  best_size_index = i;
3630                               }
3631                          }
3632                     }
3633                   if (((best_size.width != -1) && (best_size.height != -1)) &&
3634                       ((best_size.width != screen_size.width) ||
3635                        (best_size.height != screen_size.height)))
3636                     {
3637                        if (ecore_x_randr_screen_primary_output_size_set(bd->zone->container->manager->root,
3638                                                                         best_size_index))
3639                          screen_size_index = best_size_index;
3640                        e_border_move_resize(bd, 0, 0, best_size.width, best_size.height);
3641                     }
3642                   else
3643                     {
3644                        screen_size.width = -1;
3645                        screen_size.height = -1;
3646                        e_border_move_resize(bd, 0, 0, bd->zone->w, bd->zone->h);
3647                     }
3648                   free(sizes);
3649                }
3650              else
3651                e_border_move_resize(bd, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h);
3652           }
3653         bd->fullscreen = 1;
3654
3655         e_hints_window_fullscreen_set(bd, 1);
3656         e_hints_window_size_unset(bd);
3657         bd->client.border.changed = 1;
3658         bd->changed = 1;
3659      }
3660    bd->fullscreen_policy = policy;
3661
3662    ev = E_NEW(E_Event_Border_Fullscreen, 1);
3663    ev->border = bd;
3664    e_object_ref(E_OBJECT(bd));
3665    //   e_object_breadcrumb_add(E_OBJECT(bd), "border_fullscreen_event");
3666    ecore_event_add(E_EVENT_BORDER_FULLSCREEN, ev, _e_border_event_border_fullscreen_free, NULL);
3667
3668    e_remember_update(bd);
3669 }
3670
3671 EAPI void
3672 e_border_unfullscreen(E_Border *bd)
3673 {
3674    E_Event_Border_Unfullscreen *ev;
3675
3676    E_OBJECT_CHECK(bd);
3677    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3678    if ((bd->shaded) || (bd->shading)) return;
3679    ecore_x_window_shadow_tree_flush();
3680    if (bd->fullscreen)
3681      {
3682         bd->pre_res_change.valid = 0;
3683         bd->fullscreen = 0;
3684         bd->need_fullscreen = 0;
3685         bd->desk->fullscreen_borders--;
3686
3687         if ((screen_size.width != -1) && (screen_size.height != -1))
3688           {
3689              ecore_x_randr_screen_primary_output_size_set(bd->zone->container->manager->root,
3690                                                           screen_size_index);
3691              screen_size.width = -1;
3692              screen_size.height = -1;
3693           }
3694         e_border_move_resize(bd,
3695                              bd->saved.x + bd->zone->x,
3696                              bd->saved.y + bd->zone->y,
3697                              bd->saved.w, bd->saved.h);
3698
3699         if (bd->saved.maximized)
3700           e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) |
3701                             bd->saved.maximized);
3702
3703         e_border_layer_set(bd, bd->saved.layer);
3704
3705         e_hints_window_fullscreen_set(bd, 0);
3706         bd->client.border.changed = 1;
3707         bd->changed = 1;
3708      }
3709    bd->fullscreen_policy = 0;
3710
3711    ev = E_NEW(E_Event_Border_Unfullscreen, 1);
3712    ev->border = bd;
3713    e_object_ref(E_OBJECT(bd));
3714    //   e_object_breadcrumb_add(E_OBJECT(bd), "border_unfullscreen_event");
3715    ecore_event_add(E_EVENT_BORDER_UNFULLSCREEN, ev, _e_border_event_border_unfullscreen_free, NULL);
3716
3717    e_remember_update(bd);
3718 }
3719
3720 EAPI void
3721 e_border_iconify(E_Border *bd)
3722 {
3723    E_Event_Border_Iconify *ev;
3724    unsigned int iconic;
3725
3726    E_OBJECT_CHECK(bd);
3727    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3728    if (bd->shading) return;
3729    ecore_x_window_shadow_tree_flush();
3730    if (!bd->iconic)
3731      {
3732         bd->iconic = 1;
3733         e_border_hide(bd, 1);
3734         if (bd->fullscreen) bd->desk->fullscreen_borders--;
3735         edje_object_signal_emit(bd->bg_object, "e,action,iconify", "e");
3736      }
3737    iconic = 1;
3738    e_hints_window_iconic_set(bd);
3739    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
3740
3741    ev = E_NEW(E_Event_Border_Iconify, 1);
3742    ev->border = bd;
3743    e_object_ref(E_OBJECT(bd));
3744 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_iconify_event");
3745    ecore_event_add(E_EVENT_BORDER_ICONIFY, ev, _e_border_event_border_iconify_free, NULL);
3746
3747    if (e_config->transient.iconify)
3748      {
3749         Eina_List *l;
3750         E_Border *child;
3751         Eina_List *list = _e_border_sub_borders_new(bd);
3752
3753         EINA_LIST_FOREACH(list, l, child)
3754           {
3755              e_border_iconify(child);
3756           }
3757         eina_list_free(list);
3758      }
3759    e_remember_update(bd);
3760 }
3761
3762 #ifdef _F_DEICONIFY_APPROVE_
3763 static Eina_Bool
3764 _e_border_uniconify_timeout(void *data)
3765 {
3766    E_Border *bd;
3767    E_Border *child_bd;
3768
3769    bd = data;
3770
3771    if (!e_object_is_del(E_OBJECT(bd)))
3772      {
3773         ELB(ELBT_BD, "TIMEOUT UNICONIFY_APPROVE", bd->client.win);
3774         bd->client.e.state.deiconify_approve.render_done = 1;
3775         if (bd->client.e.state.deiconify_approve.req_list)
3776           {
3777              EINA_LIST_FREE(bd->client.e.state.deiconify_approve.req_list, child_bd)
3778                {
3779                   child_bd->client.e.state.deiconify_approve.render_done = 1;
3780                   child_bd->client.e.state.deiconify_approve.ancestor = NULL;
3781                }
3782           }
3783         bd->client.e.state.deiconify_approve.req_list = NULL;
3784         bd->client.e.state.deiconify_approve.wait_timer = NULL;
3785         e_border_uniconify(bd);
3786      }
3787
3788    return ECORE_CALLBACK_CANCEL;
3789 }
3790
3791 static void
3792 _e_border_deiconify_approve_send_pending_end(void *data)
3793 {
3794    E_Border *bd = (E_Border *)data;
3795    E_Border *bd_ancestor;
3796
3797    if (e_config->deiconify_approve)
3798      {
3799         if (!e_object_is_del(E_OBJECT(bd)))
3800           {
3801              bd->client.e.state.deiconify_approve.pending_job = NULL;
3802
3803              ELBF(ELBT_BD, 0, bd->client.win,
3804                   "SEND DEICONIFY_APPROVE. (PENDING_END) ancestor:%x",
3805                   bd->client.win);
3806
3807              ecore_x_client_message32_send(bd->client.win,
3808                                            ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3809                                            ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3810                                            bd->client.win, 0, 0, 0, 0);
3811              bd_ancestor = bd->client.e.state.deiconify_approve.ancestor;
3812              if (bd_ancestor)
3813                {
3814                   bd_ancestor->client.e.state.deiconify_approve.req_list = eina_list_append(bd_ancestor->client.e.state.deiconify_approve.req_list, bd);
3815                }
3816
3817              if (!bd->client.e.state.deiconify_approve.wait_timer)
3818                bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
3819           }
3820      }
3821 }
3822
3823 static void
3824 _e_border_deiconify_approve_send(E_Border *bd, E_Border *bd_ancestor, Eina_Bool pending_ancestor)
3825 {
3826    if (!bd || !bd_ancestor) return;
3827
3828    if (e_config->deiconify_approve)
3829      {
3830         if (e_config->transient.iconify)
3831           {
3832              Eina_List *l;
3833              E_Border *child;
3834              Eina_List *list = _e_border_sub_borders_new(bd);
3835              EINA_LIST_FOREACH(list, l, child)
3836                {
3837                   Eina_Bool pending = EINA_FALSE;
3838                   Eina_Bool p = EINA_FALSE;
3839
3840 #ifdef _F_ZONE_WINDOW_ROTATION_
3841                   if ((e_config->wm_win_rotation) &&
3842                       ((child->client.e.state.rot.support) ||
3843                        (child->client.e.state.rot.app_set)))
3844                     {
3845                        ELB(ELBT_ROT, "CHECK_DEICONIFY CHILD", child->client.win);
3846                        int rotation = _e_border_rotation_angle_get(bd);
3847                        if (rotation != -1) _e_border_rotation_set_internal(bd, rotation, &pending);
3848                     }
3849 #endif
3850                   if ((pending_ancestor) || (pending)) p = EINA_TRUE;
3851
3852                   _e_border_deiconify_approve_send(child, bd_ancestor, p);
3853                   if (child->client.e.state.deiconify_approve.support)
3854                     {
3855                        if (!p)
3856                          {
3857                             ELBF(ELBT_BD, 0, child->client.win,
3858                                  "SEND DEICONIFY_APPROVE. ancestor:%x pending(%d,%d)",
3859                                  bd_ancestor->client.win,
3860                                  pending_ancestor, pending);
3861
3862                             ecore_x_client_message32_send(child->client.win,
3863                                                           ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3864                                                           ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3865                                                           child->client.win, 0, 0, 0, 0);
3866                             child->client.e.state.deiconify_approve.ancestor = bd_ancestor;
3867                             bd_ancestor->client.e.state.deiconify_approve.req_list = eina_list_append(bd_ancestor->client.e.state.deiconify_approve.req_list, child);
3868                          }
3869                        else
3870                          {
3871                             /* queue a deiconify send job to give the chance to other jobs */
3872                             ELBF(ELBT_BD, 0, child->client.win,
3873                                  "SEND DEICONIFY_APPROVE. (PENDING) ancestor:%x",
3874                                  bd_ancestor->client.win);
3875                             child->client.e.state.deiconify_approve.ancestor = bd_ancestor;
3876                             child->client.e.state.deiconify_approve.pending_job = ecore_job_add(_e_border_deiconify_approve_send_pending_end, child);
3877                          }
3878                     }
3879                }
3880              eina_list_free(list);
3881           }
3882      }
3883 }
3884
3885 static void
3886 _e_border_deiconify_approve_send_all_transient(E_Border *bd)
3887 {
3888    Eina_Bool pending = EINA_FALSE;
3889
3890    if (e_config->deiconify_approve)
3891      {
3892 #ifdef _F_ZONE_WINDOW_ROTATION_
3893         if ((e_config->wm_win_rotation) &&
3894             ((bd->client.e.state.rot.support) ||
3895              (bd->client.e.state.rot.app_set)))
3896           {
3897              ELB(ELBT_ROT, "CHECK_DEICONIFY", bd->client.win);
3898              int rotation = _e_border_rotation_angle_get(bd);
3899              if (rotation != -1) _e_border_rotation_set_internal(bd, rotation, &pending);
3900           }
3901 #endif
3902
3903         if (e_config->transient.iconify)
3904           {
3905              _e_border_deiconify_approve_send(bd, bd, pending);
3906           }
3907
3908         if (bd->client.e.state.deiconify_approve.support)
3909           {
3910              if (!pending)
3911                {
3912                   ELBF(ELBT_BD, 0, bd->client.win, "SEND DEICONIFY_APPROVE.");
3913                   ecore_x_client_message32_send(bd->client.win,
3914                                                 ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3915                                                 ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3916                                                 bd->client.win, 0, 0, 0, 0);
3917                   bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
3918                }
3919              else
3920                {
3921                   /* queue a deiconify send job to give the chance to other jobs */
3922                   ELBF(ELBT_BD, 0, bd->client.win, "SEND DEICONIFY_APPROVE. (PENDING)");
3923                   bd->client.e.state.deiconify_approve.pending_job = ecore_job_add(_e_border_deiconify_approve_send_pending_end, bd);
3924                }
3925           }
3926      }
3927 }
3928 #endif
3929
3930 EAPI void
3931 e_border_uniconify(E_Border *bd)
3932 {
3933    E_Desk *desk;
3934    E_Event_Border_Uniconify *ev;
3935    unsigned int iconic;
3936
3937    E_OBJECT_CHECK(bd);
3938    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3939
3940 #ifdef _F_DEICONIFY_APPROVE_
3941    if (e_config->deiconify_approve)
3942      {
3943         if (bd->client.e.state.deiconify_approve.support)
3944           {
3945              if (bd->client.e.state.deiconify_approve.wait_timer)
3946                {
3947                   ELB(ELBT_BD, "DEICONIFY_APPROVE WAIT_TIMER is already running", bd->client.win);
3948                   return;
3949                }
3950
3951              if (bd->client.e.state.deiconify_approve.pending_job)
3952                {
3953                   ELB(ELBT_BD, "DEICONIFY_APPROVE PENDING_JOB is already running", bd->client.win);
3954                   return;
3955                }
3956
3957              if (bd->client.e.state.deiconify_approve.render_done == 0)
3958                {
3959                   ELB(ELBT_BD, "DEICONIFY_APPROVE to all transient", bd->client.win);
3960                   _e_border_deiconify_approve_send_all_transient(bd);
3961                   return;
3962                }
3963           }
3964         bd->client.e.state.deiconify_approve.render_done = 0;
3965      }
3966 #endif
3967
3968 #if _F_ZONE_WINDOW_ROTATION_
3969    if (!bd->client.win)
3970      {
3971         ELB(ELBT_DFT, "ERR! obj is already deleted", bd->client.win);
3972         return;
3973      }
3974 #endif
3975
3976    if (bd->shading) return;
3977    ecore_x_window_shadow_tree_flush();
3978    e_border_show(bd);
3979    if (bd->iconic)
3980      {
3981         bd->iconic = 0;
3982         if (bd->fullscreen) bd->desk->fullscreen_borders++;
3983         desk = e_desk_current_get(bd->desk->zone);
3984 #ifdef _F_USE_EXTENDED_ICONIFY_
3985         if (e_manager_comp_evas_get(bd->zone->container->manager))
3986           {
3987              if (bd->await_hide_event > 0)
3988                bd->await_hide_event--;
3989           }
3990 #endif
3991         e_border_desk_set(bd, desk);
3992         e_border_raise(bd);
3993         edje_object_signal_emit(bd->bg_object, "e,action,uniconify", "e");
3994      }
3995    iconic = 0;
3996    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
3997
3998    ev = E_NEW(E_Event_Border_Uniconify, 1);
3999    ev->border = bd;
4000    e_object_ref(E_OBJECT(bd));
4001 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_uniconify_event");
4002    ecore_event_add(E_EVENT_BORDER_UNICONIFY, ev, _e_border_event_border_uniconify_free, NULL);
4003
4004    if (e_config->transient.iconify)
4005      {
4006         Eina_List *l;
4007         E_Border *child;
4008         Eina_List *list = _e_border_sub_borders_new(bd);
4009
4010         EINA_LIST_FOREACH(list, l, child)
4011           {
4012              e_border_uniconify(child);
4013           }
4014         eina_list_free(list);
4015      }
4016    e_remember_update(bd);
4017 }
4018
4019 EAPI void
4020 e_border_stick(E_Border *bd)
4021 {
4022    E_Event_Border_Stick *ev;
4023
4024    E_OBJECT_CHECK(bd);
4025    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4026    if (bd->sticky) return;
4027    bd->sticky = 1;
4028    e_hints_window_sticky_set(bd, 1);
4029    e_border_show(bd);
4030
4031    if (e_config->transient.desktop)
4032      {
4033         Eina_List *l;
4034         E_Border *child;
4035         Eina_List *list = _e_border_sub_borders_new(bd);
4036
4037         EINA_LIST_FOREACH(list, l, child)
4038           {
4039              child->sticky = 1;
4040              e_hints_window_sticky_set(child, 1);
4041              e_border_show(child);
4042           }
4043         eina_list_free(list);
4044      }
4045
4046    edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
4047    ev = E_NEW(E_Event_Border_Stick, 1);
4048    ev->border = bd;
4049    e_object_ref(E_OBJECT(bd));
4050 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_stick_event");
4051    ecore_event_add(E_EVENT_BORDER_STICK, ev, _e_border_event_border_stick_free, NULL);
4052    e_remember_update(bd);
4053 }
4054
4055 EAPI void
4056 e_border_unstick(E_Border *bd)
4057 {
4058    E_Event_Border_Unstick *ev;
4059
4060    E_OBJECT_CHECK(bd);
4061    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4062    /* Set the desk before we unstick the border */
4063    if (!bd->sticky) return;
4064    bd->sticky = 0;
4065    e_hints_window_sticky_set(bd, 0);
4066
4067    if (e_config->transient.desktop)
4068      {
4069         Eina_List *l;
4070         E_Border *child;
4071         Eina_List *list = _e_border_sub_borders_new(bd);
4072
4073         EINA_LIST_FOREACH(list, l, child)
4074           {
4075              child->sticky = 0;
4076              e_hints_window_sticky_set(child, 0);
4077           }
4078         eina_list_free(list);
4079      }
4080
4081    edje_object_signal_emit(bd->bg_object, "e,state,unsticky", "e");
4082    ev = E_NEW(E_Event_Border_Unstick, 1);
4083    ev->border = bd;
4084    e_object_ref(E_OBJECT(bd));
4085 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_unstick_event");
4086    ecore_event_add(E_EVENT_BORDER_UNSTICK, ev, _e_border_event_border_unstick_free, NULL);
4087
4088    e_border_desk_set(bd, e_desk_current_get(bd->zone));
4089    e_remember_update(bd);
4090 }
4091
4092 EAPI void
4093 e_border_pinned_set(E_Border *bd,
4094                     int       set)
4095 {
4096    int layer;
4097    int stacking;
4098
4099    if (bd)
4100      {
4101         bd->borderless = set;
4102         bd->user_skip_winlist = set;
4103         if (set)
4104           {
4105              layer = 50;
4106              stacking = E_STACKING_BELOW;
4107           }
4108         else
4109           {
4110              layer = 100;
4111              stacking = E_STACKING_NONE;
4112           }
4113
4114         e_border_layer_set(bd, layer);
4115         e_hints_window_stacking_set(bd, stacking);
4116
4117         bd->client.border.changed = 1;
4118         bd->changed = 1;
4119      }
4120 }
4121
4122 EAPI E_Border *
4123 e_border_find_by_client_window(Ecore_X_Window win)
4124 {
4125    E_Border *bd;
4126
4127    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4128    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4129        (bd->client.win == win))
4130      return bd;
4131    return NULL;
4132 }
4133
4134 EAPI E_Border *
4135 e_border_find_all_by_client_window(Ecore_X_Window win)
4136 {
4137    E_Border *bd;
4138
4139    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4140    if ((bd) && (bd->client.win == win))
4141      return bd;
4142    return NULL;
4143 }
4144
4145 EAPI E_Border *
4146 e_border_find_by_frame_window(Ecore_X_Window win)
4147 {
4148    E_Border *bd;
4149
4150    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4151    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4152        (bd->bg_win == win))
4153      return bd;
4154    return NULL;
4155 }
4156
4157 EAPI E_Border *
4158 e_border_find_by_window(Ecore_X_Window win)
4159 {
4160    E_Border *bd;
4161
4162    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4163    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4164        (bd->win == win))
4165      return bd;
4166    return NULL;
4167 }
4168
4169 EAPI E_Border *
4170 e_border_find_by_alarm(Ecore_X_Sync_Alarm al)
4171 {
4172    Eina_List *l;
4173    E_Border *bd;
4174
4175    EINA_LIST_FOREACH(borders, l, bd)
4176      {
4177         if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4178             (bd->client.netwm.sync.alarm == al))
4179           return bd;
4180      }
4181    return NULL;
4182 }
4183
4184 EAPI E_Border *
4185 e_border_focused_get(void)
4186 {
4187    return focused;
4188 }
4189
4190 static void
4191 _e_border_shape_input_rectangle_set(E_Border* bd)
4192 {
4193    if (!bd) return;
4194
4195    if ((bd->visible) && (bd->shaped_input))
4196      {
4197         Ecore_X_Rectangle rects[4];
4198         Ecore_X_Window twin, twin2;
4199         int x, y;
4200
4201         twin = ecore_x_window_override_new(bd->zone->container->scratch_win,
4202                                            0, 0, bd->w, bd->h);
4203         rects[0].x = 0;
4204         rects[0].y = 0;
4205         rects[0].width = bd->w;
4206         rects[0].height = bd->client_inset.t;
4207         rects[1].x = 0;
4208         rects[1].y = bd->client_inset.t;
4209         rects[1].width = bd->client_inset.l;
4210         rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
4211         rects[2].x = bd->w - bd->client_inset.r;
4212         rects[2].y = bd->client_inset.t;
4213         rects[2].width = bd->client_inset.r;
4214         rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
4215         rects[3].x = 0;
4216         rects[3].y = bd->h - bd->client_inset.b;
4217         rects[3].width = bd->w;
4218         rects[3].height = bd->client_inset.b;
4219         ecore_x_window_shape_input_rectangles_set(twin, rects, 4);
4220
4221         twin2 = ecore_x_window_override_new
4222            (bd->zone->container->scratch_win, 0, 0,
4223                bd->w - bd->client_inset.l - bd->client_inset.r,
4224                bd->h - bd->client_inset.t - bd->client_inset.b);
4225         x = 0;
4226         y = 0;
4227         if ((bd->shading) || (bd->shaded))
4228           {
4229              if (bd->shade.dir == E_DIRECTION_UP)
4230                 y = bd->h - bd->client_inset.t - bd->client_inset.b -
4231                 bd->client.h;
4232              else if (bd->shade.dir == E_DIRECTION_LEFT)
4233                 x = bd->w - bd->client_inset.l - bd->client_inset.r -
4234                 bd->client.w;
4235           }
4236         ecore_x_window_shape_input_window_set_xy(twin2, bd->client.win,
4237                                                  x, y);
4238         ecore_x_window_shape_input_rectangle_clip(twin2, 0, 0,
4239                                                   bd->w - bd->client_inset.l - bd->client_inset.r,
4240                                                   bd->h - bd->client_inset.t - bd->client_inset.b);
4241         ecore_x_window_shape_input_window_add_xy(twin, twin2,
4242                                                  bd->client_inset.l,
4243                                                  bd->client_inset.t);
4244         ecore_x_window_shape_input_window_set(bd->win, twin);
4245         ecore_x_window_free(twin2);
4246         ecore_x_window_free(twin);
4247      }
4248    else
4249      {
4250         if (bd->visible) // not shaped input
4251           {
4252              if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
4253                 ecore_x_composite_window_events_enable(bd->win);
4254              else
4255                 ecore_x_composite_window_events_disable(bd->win);
4256           }
4257         else
4258           {
4259              if (!e_manager_comp_evas_get(bd->zone->container->manager))
4260                 ecore_x_composite_window_events_enable(bd->win);
4261              else
4262                 ecore_x_composite_window_events_disable(bd->win);
4263           }
4264      }
4265 }
4266
4267 EAPI void
4268 e_border_idler_before(void)
4269 {
4270    Eina_List *ml, *cl;
4271    E_Manager *man;
4272    E_Container *con;
4273
4274    if (!borders)
4275      return;
4276
4277    EINA_LIST_FOREACH(e_manager_list(), ml, man)
4278      {
4279         EINA_LIST_FOREACH(man->containers, cl, con)
4280           {
4281              E_Border_List *bl;
4282              E_Border *bd;
4283
4284              // pass 1 - eval0. fetch properties on new or on change and
4285              // call hooks to decide what to do - maybe move/resize
4286              bl = e_container_border_list_last(con);
4287              while ((bd = e_container_border_list_prev(bl)))
4288                {
4289                   if (bd->changed) _e_border_eval0(bd);
4290                }
4291              e_container_border_list_free(bl);
4292
4293              // layout hook - this is where a hook gets to figure out what to
4294              // do if anything.
4295              _e_border_container_layout_hook(con);
4296
4297              // pass 2 - show windows needing show
4298              bl = e_container_border_list_last(con);
4299              while ((bd = e_container_border_list_prev(bl)))
4300                {
4301                   if ((bd->changes.visible) && (bd->visible) &&
4302                       (!bd->new_client) && (!bd->changes.pos) &&
4303                       (!bd->changes.size))
4304                     {
4305                        _e_border_show(bd);
4306                        bd->changes.visible = 0;
4307                     }
4308                }
4309              e_container_border_list_free(bl);
4310
4311              // pass 3 - hide windows needing hide and eval (main eval)
4312              bl = e_container_border_list_first(con);
4313              while ((bd = e_container_border_list_next(bl)))
4314                {
4315                   if (e_object_is_del(E_OBJECT(bd))) continue;
4316
4317                   if ((bd->changes.visible) && (!bd->visible))
4318                     {
4319                        _e_border_hide(bd);
4320                        bd->changes.visible = 0;
4321                     }
4322
4323                   if (bd->changed) _e_border_eval(bd);
4324
4325                   if ((bd->changes.visible) && (bd->visible))
4326                     {
4327                        _e_border_show(bd);
4328                        bd->changes.visible = 0;
4329                     }
4330                }
4331              e_container_border_list_free(bl);
4332           }
4333      }
4334
4335    if (focus_next)
4336      {
4337         E_Border *bd = NULL, *bd2;
4338
4339         EINA_LIST_FREE(focus_next, bd2)
4340           if ((!bd) && (bd2->visible)) bd = bd2;
4341
4342         if (!bd)
4343           {
4344              /* TODO revert focus when lost here ? */
4345              return;
4346           }
4347 #if 0
4348         if (bd == focused)
4349           {
4350              /* already focused. but anyway dont be so strict, this
4351                 fcks up illume setting focus on internal windows */
4352              return;
4353           }
4354 #endif
4355         
4356         focus_time = ecore_x_current_time_get();
4357
4358         focusing = bd;
4359
4360         if ((bd->client.icccm.take_focus) &&
4361             (bd->client.icccm.accepts_focus))
4362           {
4363              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
4364              /* TODO what if the client didn't take focus ? */
4365           }
4366         else if (!bd->client.icccm.accepts_focus)
4367           {
4368              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
4369           }
4370         else if (!bd->client.icccm.take_focus)
4371           {
4372              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
4373              /* e_border_focus_set(bd, 1, 0); */
4374           }
4375      }
4376
4377 #ifdef _F_ZONE_WINDOW_ROTATION_
4378    if ((e_config->wm_win_rotation) &&
4379        (rot.fetch))
4380      {
4381         Ecore_X_Event_Client_Message *msg = NULL;
4382         Ecore_X_Atom t = 0;
4383         EINA_LIST_FREE(rot.msgs, msg)
4384           {
4385              t = msg->message_type;
4386              if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)
4387                {
4388                   if ((rot.vkbd_ctrl_win) &&
4389                       ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) &&
4390                       (rot.vkbd))
4391                     {
4392                        ELB(ELBT_BD, "GET KBD_ON_PREPARE_DONE", rot.vkbd_ctrl_win);
4393                        if (rot.vkbd_show_prepare_timer)
4394                          _e_border_vkbd_show(rot.vkbd);
4395                        else
4396                          ELB(ELBT_BD, "GET KBD_ON_PREPARE_DONE but skip", rot.vkbd_ctrl_win);
4397                     }
4398                }
4399              else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE)
4400                {
4401                   if ((rot.vkbd_ctrl_win) &&
4402                       ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) &&
4403                       (rot.vkbd))
4404                     {
4405                        ELB(ELBT_BD, "GET KBD_OFF_PREPARE_DONE", rot.vkbd_ctrl_win);
4406                        if (rot.vkbd_hide_prepare_timer)
4407                          {
4408                             _e_border_vkbd_hide(rot.vkbd);
4409                             rot.vkbd_hide_prepare_timer = NULL;
4410                             e_object_unref(E_OBJECT(rot.vkbd));
4411                          }
4412                        else
4413                          ELB(ELBT_BD, "GET KBD_OFF_PREPARE_DONE but skip", rot.vkbd_ctrl_win);
4414                     }
4415                }
4416              else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)
4417                {
4418                   rot.vkbd_ctrl_win = msg->data.l[0];
4419                   ELB(ELBT_BD, "SET KBD_CONTROL_WIN", rot.vkbd_ctrl_win);
4420                }
4421              else if (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE)
4422                {
4423                   if ((rot.vkbd_ctrl_win) &&
4424                       (rot.vkbd_ctrl_win == (Ecore_X_Window)msg->data.l[0]))
4425                     {
4426                        ELB(ELBT_ROT, "GET ROT_PREPARE_DONE", rot.vkbd_ctrl_win);
4427                        E_Manager *m = e_manager_current_get();
4428                        E_Zone *zone = NULL;
4429                        if (m) zone = e_util_zone_current_get(m);
4430                        if ((zone) && (rot.wait_prepare_done))
4431                          {
4432                             if (rot.list)
4433                               _e_border_rotation_change_request(zone);
4434                             else if (rot.async_list)
4435                               {
4436                                  _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
4437                                  rot.async_list = NULL;
4438                               }
4439                             if (rot.prepare_timer)
4440                               ecore_timer_del(rot.prepare_timer);
4441                             rot.prepare_timer = NULL;
4442                             rot.wait_prepare_done = EINA_FALSE;
4443                          }
4444                     }
4445                }
4446              E_FREE(msg);
4447           }
4448         rot.msgs = NULL;
4449         rot.fetch = EINA_FALSE;
4450      }
4451 #endif
4452 }
4453
4454 EAPI Eina_List *
4455 e_border_client_list(void)
4456 {
4457    /* FIXME: This should be a somewhat ordered list */
4458    return borders;
4459 }
4460
4461 static Ecore_X_Window action_input_win = 0;
4462 static E_Border *action_border = NULL;
4463 static Ecore_Event_Handler *action_handler_key = NULL;
4464 static Ecore_Event_Handler *action_handler_mouse = NULL;
4465 static Ecore_Timer *action_timer = NULL;
4466 static Ecore_X_Rectangle action_orig;
4467
4468 static void
4469 _e_border_show(E_Border *bd)
4470 {
4471    Eina_List *l;
4472    E_Border *tmp;
4473
4474    ecore_evas_show(bd->bg_ecore_evas);
4475
4476    if (bd->post_job)
4477      {
4478         bd->post_show = 1;
4479         return;
4480      }
4481
4482    if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
4483      {
4484         _e_border_shape_input_rectangle_set(bd);
4485         // not anymore
4486         //      ecore_x_composite_window_events_enable(bd->win);
4487         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
4488      }
4489
4490    ecore_x_window_show(bd->win);
4491
4492    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
4493      ecore_x_window_show(tmp->win);
4494 }
4495
4496 static void
4497 _e_border_hide(E_Border *bd)
4498 {
4499    E_Border *tmp;
4500    Eina_List *l;
4501
4502    if (!e_manager_comp_evas_get(bd->zone->container->manager))
4503      {
4504         ecore_x_window_hide(bd->win);
4505         ecore_evas_hide(bd->bg_ecore_evas);
4506
4507         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
4508           ecore_x_window_hide(tmp->win);
4509      }
4510    else
4511      {
4512         ecore_x_composite_window_events_disable(bd->win);
4513         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
4514      }
4515 }
4516
4517 static int
4518 _e_border_action_input_win_del(void)
4519 {
4520    if (!action_input_win)
4521      return 0;
4522
4523    e_grabinput_release(action_input_win, action_input_win);
4524    ecore_x_window_free(action_input_win);
4525    action_input_win = 0;
4526    return 1;
4527 }
4528
4529 static int
4530 _e_border_action_input_win_new(E_Border *bd)
4531 {
4532    if (!action_input_win)
4533      {
4534         Ecore_X_Window parent = bd->zone->container->win;
4535         action_input_win = ecore_x_window_input_new(parent, 0, 0, 1, 1);
4536         if (!action_input_win)
4537           return 0;
4538      }
4539
4540    ecore_x_window_show(action_input_win);
4541    if (e_grabinput_get(action_input_win, 0, action_input_win))
4542      return 1;
4543
4544    _e_border_action_input_win_del();
4545    return 0;
4546 }
4547
4548 static void
4549 _e_border_action_finish(void)
4550 {
4551    _e_border_action_input_win_del();
4552
4553    if (action_timer)
4554      {
4555         ecore_timer_del(action_timer);
4556         action_timer = NULL;
4557      }
4558
4559    if (action_handler_key)
4560      {
4561         ecore_event_handler_del(action_handler_key);
4562         action_handler_key = NULL;
4563      }
4564
4565    if (action_handler_mouse)
4566      {
4567         ecore_event_handler_del(action_handler_mouse);
4568         action_handler_mouse = NULL;
4569      }
4570
4571    action_border = NULL;
4572 }
4573
4574 static void
4575 _e_border_action_init(E_Border *bd)
4576 {
4577    action_orig.x = bd->x;
4578    action_orig.y = bd->y;
4579    action_orig.width = bd->w;
4580    action_orig.height = bd->h;
4581
4582    action_border = bd;
4583 }
4584
4585 static void
4586 _e_border_action_restore_orig(E_Border *bd)
4587 {
4588    if (action_border != bd)
4589      return;
4590
4591    e_border_move_resize(bd, action_orig.x, action_orig.y, action_orig.width, action_orig.height);
4592 }
4593
4594 static int
4595 _e_border_key_down_modifier_apply(int modifier,
4596                                   int value)
4597 {
4598    if (modifier & ECORE_EVENT_MODIFIER_CTRL)
4599      return value * 2;
4600    else if (modifier & ECORE_EVENT_MODIFIER_ALT)
4601      {
4602         value /= 2;
4603         if (value)
4604           return value;
4605         else
4606           return 1;
4607      }
4608
4609    return value;
4610 }
4611
4612 static Eina_Bool
4613 _e_border_action_move_timeout(void *data __UNUSED__)
4614 {
4615    _e_border_move_end(action_border);
4616    _e_border_action_finish();
4617    return ECORE_CALLBACK_CANCEL;
4618 }
4619
4620 static void
4621 _e_border_action_move_timeout_add(void)
4622 {
4623    if (action_timer)
4624      ecore_timer_del(action_timer);
4625    action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_move_timeout, NULL);
4626 }
4627
4628 static Eina_Bool
4629 _e_border_move_key_down(void *data __UNUSED__,
4630                         int type   __UNUSED__,
4631                         void      *event)
4632 {
4633    Ecore_Event_Key *ev = event;
4634    int x, y;
4635
4636    if (ev->event_window != action_input_win)
4637      return ECORE_CALLBACK_PASS_ON;
4638    if (!action_border)
4639      {
4640         fputs("ERROR: no action_border!\n", stderr);
4641         goto stop;
4642      }
4643
4644    x = action_border->x;
4645    y = action_border->y;
4646
4647    if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
4648      y -= _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dy);
4649    else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
4650      y += _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dy);
4651    else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
4652      x -= _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dx);
4653    else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
4654      x += _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dx);
4655    else if (strcmp(ev->key, "Return") == 0)
4656      goto stop;
4657    else if (strcmp(ev->key, "Escape") == 0)
4658      {
4659         _e_border_action_restore_orig(action_border);
4660         goto stop;
4661      }
4662    else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
4663             (strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
4664      goto stop;
4665
4666    e_border_move(action_border, x, y);
4667    _e_border_action_move_timeout_add();
4668
4669    return ECORE_CALLBACK_PASS_ON;
4670
4671 stop:
4672    _e_border_move_end(action_border);
4673    _e_border_action_finish();
4674    return ECORE_CALLBACK_DONE;
4675 }
4676
4677 static Eina_Bool
4678 _e_border_move_mouse_down(void *data __UNUSED__,
4679                           int type   __UNUSED__,
4680                           void      *event)
4681 {
4682    Ecore_Event_Mouse_Button *ev = event;
4683
4684    if (ev->event_window != action_input_win)
4685      return ECORE_CALLBACK_PASS_ON;
4686
4687    if (!action_border)
4688      fputs("ERROR: no action_border!\n", stderr);
4689
4690    _e_border_move_end(action_border);
4691    _e_border_action_finish();
4692    return ECORE_CALLBACK_DONE;
4693 }
4694
4695 EAPI void
4696 e_border_act_move_keyboard(E_Border *bd)
4697 {
4698    if (!bd)
4699      return;
4700
4701    if (!_e_border_move_begin(bd))
4702      return;
4703
4704    if (!_e_border_action_input_win_new(bd))
4705      {
4706         _e_border_move_end(bd);
4707         return;
4708      }
4709
4710    _e_border_action_init(bd);
4711    _e_border_action_move_timeout_add();
4712    _e_border_move_update(bd);
4713
4714    if (action_handler_key)
4715      ecore_event_handler_del(action_handler_key);
4716    action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_move_key_down, NULL);
4717
4718    if (action_handler_mouse)
4719      ecore_event_handler_del(action_handler_mouse);
4720    action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_move_mouse_down, NULL);
4721 }
4722
4723 static Eina_Bool
4724 _e_border_action_resize_timeout(void *data __UNUSED__)
4725 {
4726    _e_border_resize_end(action_border);
4727    _e_border_action_finish();
4728    return ECORE_CALLBACK_CANCEL;
4729 }
4730
4731 static void
4732 _e_border_action_resize_timeout_add(void)
4733 {
4734    if (action_timer)
4735      ecore_timer_del(action_timer);
4736    action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_resize_timeout, NULL);
4737 }
4738
4739 static Eina_Bool
4740 _e_border_resize_key_down(void *data __UNUSED__,
4741                           int type   __UNUSED__,
4742                           void      *event)
4743 {
4744    Ecore_Event_Key *ev = event;
4745    int w, h, dx, dy;
4746
4747    if (ev->event_window != action_input_win)
4748      return ECORE_CALLBACK_PASS_ON;
4749    if (!action_border)
4750      {
4751         fputs("ERROR: no action_border!\n", stderr);
4752         goto stop;
4753      }
4754
4755    w = action_border->w;
4756    h = action_border->h;
4757
4758    dx = e_config->border_keyboard.resize.dx;
4759    if (dx < action_border->client.icccm.step_w)
4760      dx = action_border->client.icccm.step_w;
4761    dx = _e_border_key_down_modifier_apply(ev->modifiers, dx);
4762    if (dx < action_border->client.icccm.step_w)
4763      dx = action_border->client.icccm.step_w;
4764
4765    dy = e_config->border_keyboard.resize.dy;
4766    if (dy < action_border->client.icccm.step_h)
4767      dy = action_border->client.icccm.step_h;
4768    dy = _e_border_key_down_modifier_apply(ev->modifiers, dy);
4769    if (dy < action_border->client.icccm.step_h)
4770      dy = action_border->client.icccm.step_h;
4771
4772    if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
4773      h -= dy;
4774    else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
4775      h += dy;
4776    else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
4777      w -= dx;
4778    else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
4779      w += dx;
4780    else if (strcmp(ev->key, "Return") == 0)
4781      goto stop;
4782    else if (strcmp(ev->key, "Escape") == 0)
4783      {
4784         _e_border_action_restore_orig(action_border);
4785         goto stop;
4786      }
4787    else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
4788             (strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
4789      goto stop;
4790
4791    e_border_resize_limit(action_border, &w, &h);
4792    e_border_resize(action_border, w, h);
4793    _e_border_action_resize_timeout_add();
4794
4795    return ECORE_CALLBACK_PASS_ON;
4796
4797 stop:
4798    _e_border_resize_end(action_border);
4799    _e_border_action_finish();
4800    return ECORE_CALLBACK_DONE;
4801 }
4802
4803 static Eina_Bool
4804 _e_border_resize_mouse_down(void *data __UNUSED__,
4805                             int type   __UNUSED__,
4806                             void      *event)
4807 {
4808    Ecore_Event_Mouse_Button *ev = event;
4809
4810    if (ev->event_window != action_input_win)
4811      return ECORE_CALLBACK_PASS_ON;
4812
4813    if (!action_border)
4814      fputs("ERROR: no action_border!\n", stderr);
4815
4816    _e_border_resize_end(action_border);
4817    _e_border_action_finish();
4818    return ECORE_CALLBACK_DONE;
4819 }
4820
4821 EAPI void
4822 e_border_act_resize_keyboard(E_Border *bd)
4823 {
4824    if (!bd)
4825      return;
4826
4827    if (!_e_border_resize_begin(bd))
4828      return;
4829
4830    if (!_e_border_action_input_win_new(bd))
4831      {
4832         _e_border_resize_end(bd);
4833         return;
4834      }
4835
4836    _e_border_action_init(bd);
4837    _e_border_action_resize_timeout_add();
4838    _e_border_resize_update(bd);
4839
4840    if (action_handler_key)
4841      ecore_event_handler_del(action_handler_key);
4842    action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_resize_key_down, NULL);
4843
4844    if (action_handler_mouse)
4845      ecore_event_handler_del(action_handler_mouse);
4846    action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_resize_mouse_down, NULL);
4847 }
4848
4849 EAPI void
4850 e_border_act_move_begin(E_Border                 *bd,
4851                         Ecore_Event_Mouse_Button *ev)
4852 {
4853    E_OBJECT_CHECK(bd);
4854    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4855    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
4856    if (!_e_border_move_begin(bd))
4857      return;
4858
4859    e_zone_edge_disable();
4860    bd->moving = 1;
4861    _e_border_pointer_move_begin(bd);
4862    if (ev)
4863      {
4864         char source[256];
4865
4866         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->buttons);
4867         _e_border_moveinfo_gather(bd, source);
4868      }
4869 }
4870
4871 EAPI void
4872 e_border_act_move_end(E_Border                    *bd,
4873                       Ecore_Event_Mouse_Button *ev __UNUSED__)
4874 {
4875    E_OBJECT_CHECK(bd);
4876    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4877    if (!bd->moving) return;
4878    bd->moving = 0;
4879    _e_border_pointer_move_end(bd);
4880    e_zone_edge_enable();
4881    _e_border_move_end(bd);
4882    e_zone_flip_coords_handle(bd->zone, -1, -1);
4883 }
4884
4885 EAPI void
4886 e_border_act_resize_begin(E_Border                 *bd,
4887                           Ecore_Event_Mouse_Button *ev)
4888 {
4889    E_OBJECT_CHECK(bd);
4890    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4891    if (bd->lock_user_size) return;
4892    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
4893    if (!_e_border_resize_begin(bd))
4894      return;
4895    if (bd->mouse.current.mx < (bd->x + bd->w / 2))
4896      {
4897         if (bd->mouse.current.my < (bd->y + bd->h / 2))
4898           {
4899              bd->resize_mode = RESIZE_TL;
4900              GRAV_SET(bd, ECORE_X_GRAVITY_SE);
4901           }
4902         else
4903           {
4904              bd->resize_mode = RESIZE_BL;
4905              GRAV_SET(bd, ECORE_X_GRAVITY_NE);
4906           }
4907      }
4908    else
4909      {
4910         if (bd->mouse.current.my < (bd->y + bd->h / 2))
4911           {
4912              bd->resize_mode = RESIZE_TR;
4913              GRAV_SET(bd, ECORE_X_GRAVITY_SW);
4914           }
4915         else
4916           {
4917              bd->resize_mode = RESIZE_BR;
4918              GRAV_SET(bd, ECORE_X_GRAVITY_NW);
4919           }
4920      }
4921    _e_border_pointer_resize_begin(bd);
4922    if (ev)
4923      {
4924         char source[256];
4925
4926         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->buttons);
4927         _e_border_moveinfo_gather(bd, source);
4928      }
4929 }
4930
4931 EAPI void
4932 e_border_act_resize_end(E_Border                    *bd,
4933                         Ecore_Event_Mouse_Button *ev __UNUSED__)
4934 {
4935    E_OBJECT_CHECK(bd);
4936    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4937    if (bd->resize_mode != RESIZE_NONE)
4938      {
4939         _e_border_pointer_resize_end(bd);
4940         bd->resize_mode = RESIZE_NONE;
4941         _e_border_resize_end(bd);
4942         bd->changes.reset_gravity = 1;
4943         bd->changed = 1;
4944      }
4945 }
4946
4947 EAPI void
4948 e_border_act_menu_begin(E_Border                 *bd,
4949                         Ecore_Event_Mouse_Button *ev,
4950                         int                       key)
4951 {
4952    E_OBJECT_CHECK(bd);
4953    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4954    if (ev)
4955      {
4956         e_int_border_menu_show(bd,
4957                                bd->x + bd->fx.x + ev->x - bd->zone->container->x,
4958                                bd->y + bd->fx.y + ev->y - bd->zone->container->y, key,
4959                                ev->timestamp);
4960      }
4961    else
4962      {
4963         int x, y;
4964
4965         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
4966         e_int_border_menu_show(bd, x, y, key, 0);
4967      }
4968 }
4969
4970 EAPI void
4971 e_border_act_close_begin(E_Border *bd)
4972 {
4973    E_OBJECT_CHECK(bd);
4974    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4975    if (bd->lock_close) return;
4976    if (bd->client.icccm.delete_request)
4977      {
4978         bd->delete_requested = 1;
4979         ecore_x_window_delete_request_send(bd->client.win);
4980         if (bd->client.netwm.ping)
4981           e_border_ping(bd);
4982      }
4983    else if (e_config->kill_if_close_not_possible)
4984      {
4985         e_border_act_kill_begin(bd);
4986      }
4987 }
4988
4989 EAPI void
4990 e_border_act_kill_begin(E_Border *bd)
4991 {
4992    E_OBJECT_CHECK(bd);
4993    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4994    if (bd->internal) return;
4995    if (bd->lock_close) return;
4996    if ((bd->client.netwm.pid > 1) && (e_config->kill_process))
4997      {
4998         kill(bd->client.netwm.pid, SIGINT);
4999         bd->kill_timer = ecore_timer_add(e_config->kill_timer_wait,
5000                                          _e_border_cb_kill_timer, bd);
5001      }
5002    else
5003      {
5004         if (!bd->internal) ecore_x_kill(bd->client.win);
5005      }
5006 }
5007
5008 EAPI Evas_Object *
5009 e_border_icon_add(E_Border *bd,
5010                   Evas     *evas)
5011 {
5012    Evas_Object *o;
5013
5014    E_OBJECT_CHECK_RETURN(bd, NULL);
5015    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, NULL);
5016
5017    o = NULL;
5018    if (bd->internal)
5019      {
5020         if (!bd->internal_icon)
5021           {
5022              o = e_icon_add(evas);
5023              e_util_icon_theme_set(o, "enlightenment");
5024           }
5025         else
5026           {
5027              if (!bd->internal_icon_key)
5028                {
5029                   char *ext;
5030
5031                   ext = strrchr(bd->internal_icon, '.');
5032                   if ((ext) && ((!strcmp(ext, ".edj"))))
5033                     {
5034                        o = edje_object_add(evas);
5035                        if (!edje_object_file_set(o, bd->internal_icon, "icon"))
5036                          e_util_icon_theme_set(o, "enlightenment");
5037                     }
5038                   else if (ext)
5039                     {
5040                        o = e_icon_add(evas);
5041                        e_icon_file_set(o, bd->internal_icon);
5042                     }
5043                   else
5044                     {
5045                        o = e_icon_add(evas);
5046                        if (!e_util_icon_theme_set(o, bd->internal_icon))
5047                          e_util_icon_theme_set(o, "enlightenment");
5048                     }
5049                }
5050              else
5051                {
5052                   o = edje_object_add(evas);
5053                   edje_object_file_set(o, bd->internal_icon,
5054                                        bd->internal_icon_key);
5055                }
5056           }
5057         return o;
5058      }
5059    if ((e_config->use_app_icon) && (bd->icon_preference != E_ICON_PREF_USER))
5060      {
5061         if (bd->client.netwm.icons)
5062           {
5063              o = e_icon_add(evas);
5064              e_icon_data_set(o, bd->client.netwm.icons[0].data,
5065                              bd->client.netwm.icons[0].width,
5066                              bd->client.netwm.icons[0].height);
5067              e_icon_alpha_set(o, 1);
5068              return o;
5069           }
5070      }
5071    if (!o)
5072      {
5073         if ((bd->desktop) && (bd->icon_preference != E_ICON_PREF_NETWM))
5074           {
5075              o = e_icon_add(evas);
5076              if (o)
5077                {
5078                   e_icon_fdo_icon_set(o, bd->desktop->icon);
5079                   return o;
5080                }
5081           }
5082         else if (bd->client.netwm.icons)
5083           {
5084              o = e_icon_add(evas);
5085              e_icon_data_set(o, bd->client.netwm.icons[0].data,
5086                              bd->client.netwm.icons[0].width,
5087                              bd->client.netwm.icons[0].height);
5088              e_icon_alpha_set(o, 1);
5089              return o;
5090           }
5091      }
5092
5093    o = e_icon_add(evas);
5094    e_util_icon_theme_set(o, "unknown");
5095    return o;
5096 }
5097
5098 EAPI void
5099 e_border_button_bindings_ungrab_all(void)
5100 {
5101    Eina_List *l;
5102    E_Border *bd;
5103
5104    EINA_LIST_FOREACH(borders, l, bd)
5105      {
5106         e_focus_setdown(bd);
5107         e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5108         e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5109      }
5110 }
5111
5112 EAPI void
5113 e_border_button_bindings_grab_all(void)
5114 {
5115    Eina_List *l;
5116    E_Border *bd;
5117
5118    EINA_LIST_FOREACH(borders, l, bd)
5119      {
5120         e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
5121         e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
5122         e_focus_setup(bd);
5123      }
5124 }
5125
5126 EAPI Eina_List *
5127 e_border_focus_stack_get(void)
5128 {
5129    return focus_stack;
5130 }
5131
5132 EAPI Eina_List *
5133 e_border_raise_stack_get(void)
5134 {
5135    return raise_stack;
5136 }
5137
5138 EAPI Eina_List *
5139 e_border_lost_windows_get(E_Zone *zone)
5140 {
5141    Eina_List *list = NULL, *l;
5142    E_Border *bd;
5143    int loss_overlap = 5;
5144
5145    E_OBJECT_CHECK_RETURN(zone, NULL);
5146    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
5147    EINA_LIST_FOREACH(borders, l, bd)
5148      {
5149         if (!bd->zone)
5150           continue;
5151
5152         if ((bd->zone != zone) ||
5153             (bd->zone->container != zone->container))
5154           continue;
5155
5156         if (!E_INTERSECTS(bd->zone->x + loss_overlap,
5157                           bd->zone->y + loss_overlap,
5158                           bd->zone->w - (2 * loss_overlap),
5159                           bd->zone->h - (2 * loss_overlap),
5160                           bd->x, bd->y, bd->w, bd->h))
5161           {
5162              list = eina_list_append(list, bd);
5163           }
5164         else if ((!E_CONTAINS(bd->zone->x, bd->zone->y,
5165                               bd->zone->w, bd->zone->h,
5166                               bd->x, bd->y, bd->w, bd->h)) &&
5167                  (bd->shaped))
5168           {
5169              Ecore_X_Rectangle *rect;
5170              int i, num;
5171
5172              rect = ecore_x_window_shape_rectangles_get(bd->win, &num);
5173              if (rect)
5174                {
5175                   int ok;
5176
5177                   ok = 0;
5178                   for (i = 0; i < num; i++)
5179                     {
5180                        if (E_INTERSECTS(bd->zone->x + loss_overlap,
5181                                         bd->zone->y + loss_overlap,
5182                                         bd->zone->w - (2 * loss_overlap),
5183                                         bd->zone->h - (2 * loss_overlap),
5184                                         rect[i].x, rect[i].y,
5185                                         (int)rect[i].width, (int)rect[i].height))
5186                          {
5187                             ok = 1;
5188                             break;
5189                          }
5190                     }
5191                   free(rect);
5192                   if (!ok)
5193                     list = eina_list_append(list, bd);
5194                }
5195           }
5196      }
5197    return list;
5198 }
5199
5200 EAPI void
5201 e_border_ping(E_Border *bd)
5202 {
5203    E_OBJECT_CHECK(bd);
5204    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5205    if (!e_config->ping_clients) return;
5206    bd->ping_ok = 0;
5207    ecore_x_netwm_ping_send(bd->client.win);
5208    bd->ping = ecore_loop_time_get();
5209    if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
5210    bd->ping_poller = ecore_poller_add(ECORE_POLLER_CORE,
5211                                       e_config->ping_clients_interval,
5212                                       _e_border_cb_ping_poller, bd);
5213 }
5214
5215 EAPI void
5216 e_border_move_cancel(void)
5217 {
5218    if (bdmove)
5219      {
5220         if (bdmove->cur_mouse_action)
5221           {
5222              E_Border *bd;
5223
5224              bd = bdmove;
5225              e_object_ref(E_OBJECT(bd));
5226              if (bd->cur_mouse_action->func.end_mouse)
5227                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
5228              else if (bd->cur_mouse_action->func.end)
5229                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
5230              e_object_unref(E_OBJECT(bd->cur_mouse_action));
5231              bd->cur_mouse_action = NULL;
5232              e_object_unref(E_OBJECT(bd));
5233           }
5234         else
5235           _e_border_move_end(bdmove);
5236      }
5237 }
5238
5239 EAPI void
5240 e_border_resize_cancel(void)
5241 {
5242    if (bdresize)
5243      {
5244         if (bdresize->cur_mouse_action)
5245           {
5246              E_Border *bd;
5247
5248              bd = bdresize;
5249              e_object_ref(E_OBJECT(bd));
5250              if (bd->cur_mouse_action->func.end_mouse)
5251                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
5252              else if (bd->cur_mouse_action->func.end)
5253                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
5254              e_object_unref(E_OBJECT(bd->cur_mouse_action));
5255              bd->cur_mouse_action = NULL;
5256              e_object_unref(E_OBJECT(bd));
5257           }
5258         else
5259           {
5260              bdresize->resize_mode = RESIZE_NONE;
5261              _e_border_resize_end(bdresize);
5262           }
5263      }
5264 }
5265
5266 EAPI void
5267 e_border_frame_recalc(E_Border *bd)
5268 {
5269    if (!bd->bg_object) return;
5270
5271    bd->w -= (bd->client_inset.l + bd->client_inset.r);
5272    bd->h -= (bd->client_inset.t + bd->client_inset.b);
5273
5274    _e_border_client_inset_calc(bd);
5275
5276    bd->w += (bd->client_inset.l + bd->client_inset.r);
5277    bd->h += (bd->client_inset.t + bd->client_inset.b);
5278
5279    bd->changed = 1;
5280    bd->changes.size = 1;
5281    if ((bd->shaped) || (bd->client.shaped))
5282      {
5283         bd->need_shape_merge = 1;
5284         bd->need_shape_export = 1;
5285      }
5286    if (bd->shaped_input)
5287      {
5288         bd->need_shape_merge = 1;
5289      }
5290    _e_border_client_move_resize_send(bd);
5291 }
5292
5293 EAPI Eina_List *
5294 e_border_immortal_windows_get(void)
5295 {
5296    Eina_List *list = NULL, *l;
5297    E_Border *bd;
5298
5299    EINA_LIST_FOREACH(borders, l, bd)
5300      {
5301         if (bd->lock_life)
5302           list = eina_list_append(list, bd);
5303      }
5304    return list;
5305 }
5306
5307 EAPI const char *
5308 e_border_name_get(const E_Border *bd)
5309 {
5310    E_OBJECT_CHECK_RETURN(bd, "");
5311    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, "");
5312    if (bd->client.netwm.name)
5313      return bd->client.netwm.name;
5314    else if (bd->client.icccm.title)
5315      return bd->client.icccm.title;
5316    return "";
5317 }
5318
5319 EAPI void
5320 e_border_signal_move_begin(E_Border       *bd,
5321                            const char     *sig,
5322                            const char *src __UNUSED__)
5323 {
5324    E_OBJECT_CHECK(bd);
5325    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5326
5327    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
5328    if (!_e_border_move_begin(bd)) return;
5329    bd->moving = 1;
5330    _e_border_pointer_move_begin(bd);
5331    e_zone_edge_disable();
5332    _e_border_moveinfo_gather(bd, sig);
5333    if (bd->cur_mouse_action)
5334      {
5335         if ((!bd->cur_mouse_action->func.end_mouse) &&
5336             (!bd->cur_mouse_action->func.end))
5337           bd->cur_mouse_action = NULL;
5338         else
5339           e_object_unref(E_OBJECT(bd->cur_mouse_action));
5340      }
5341    bd->cur_mouse_action = e_action_find("window_move");
5342    if (bd->cur_mouse_action)
5343      e_object_ref(E_OBJECT(bd->cur_mouse_action));
5344 }
5345
5346 EAPI void
5347 e_border_signal_move_end(E_Border       *bd,
5348                          const char *sig __UNUSED__,
5349                          const char *src __UNUSED__)
5350 {
5351    E_OBJECT_CHECK(bd);
5352    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5353    if (!bd->moving) return;
5354    bd->moving = 0;
5355    _e_border_pointer_move_end(bd);
5356    e_zone_edge_enable();
5357    _e_border_move_end(bd);
5358    e_zone_flip_coords_handle(bd->zone, -1, -1);
5359 }
5360
5361 EAPI int
5362 e_border_resizing_get(E_Border *bd)
5363 {
5364    E_OBJECT_CHECK_RETURN(bd, 0);
5365    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, 0);
5366    if (bd->resize_mode == RESIZE_NONE) return 0;
5367    return 1;
5368 }
5369
5370 EAPI void
5371 e_border_signal_resize_begin(E_Border       *bd,
5372                              const char     *dir,
5373                              const char     *sig,
5374                              const char *src __UNUSED__)
5375 {
5376    Ecore_X_Gravity grav = ECORE_X_GRAVITY_NW;
5377    int resize_mode = RESIZE_BR;
5378
5379    E_OBJECT_CHECK(bd);
5380    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5381
5382    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
5383    if (!_e_border_resize_begin(bd))
5384      return;
5385    if (!strcmp(dir, "tl"))
5386      {
5387         resize_mode = RESIZE_TL;
5388         grav = ECORE_X_GRAVITY_SE;
5389      }
5390    else if (!strcmp(dir, "t"))
5391      {
5392         resize_mode = RESIZE_T;
5393         grav = ECORE_X_GRAVITY_S;
5394      }
5395    else if (!strcmp(dir, "tr"))
5396      {
5397         resize_mode = RESIZE_TR;
5398         grav = ECORE_X_GRAVITY_SW;
5399      }
5400    else if (!strcmp(dir, "r"))
5401      {
5402         resize_mode = RESIZE_R;
5403         grav = ECORE_X_GRAVITY_W;
5404      }
5405    else if (!strcmp(dir, "br"))
5406      {
5407         resize_mode = RESIZE_BR;
5408         grav = ECORE_X_GRAVITY_NW;
5409      }
5410    else if (!strcmp(dir, "b"))
5411      {
5412         resize_mode = RESIZE_B;
5413         grav = ECORE_X_GRAVITY_N;
5414      }
5415    else if (!strcmp(dir, "bl"))
5416      {
5417         resize_mode = RESIZE_BL;
5418         grav = ECORE_X_GRAVITY_NE;
5419      }
5420    else if (!strcmp(dir, "l"))
5421      {
5422         resize_mode = RESIZE_L;
5423         grav = ECORE_X_GRAVITY_E;
5424      }
5425    bd->resize_mode = resize_mode;
5426    _e_border_pointer_resize_begin(bd);
5427    _e_border_moveinfo_gather(bd, sig);
5428    GRAV_SET(bd, grav);
5429    if (bd->cur_mouse_action)
5430      {
5431         if ((!bd->cur_mouse_action->func.end_mouse) &&
5432             (!bd->cur_mouse_action->func.end))
5433           bd->cur_mouse_action = NULL;
5434         else
5435           e_object_unref(E_OBJECT(bd->cur_mouse_action));
5436      }
5437    bd->cur_mouse_action = e_action_find("window_resize");
5438    if (bd->cur_mouse_action)
5439      e_object_ref(E_OBJECT(bd->cur_mouse_action));
5440 }
5441
5442 EAPI void
5443 e_border_signal_resize_end(E_Border       *bd,
5444                            const char *dir __UNUSED__,
5445                            const char *sig __UNUSED__,
5446                            const char *src __UNUSED__)
5447 {
5448    E_OBJECT_CHECK(bd);
5449    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5450    if (bd->resize_mode == RESIZE_NONE) return;
5451    _e_border_resize_handle(bd);
5452    _e_border_pointer_resize_end(bd);
5453    bd->resize_mode = RESIZE_NONE;
5454    _e_border_resize_end(bd);
5455    bd->changes.reset_gravity = 1;
5456    bd->changed = 1;
5457 }
5458
5459 EAPI void
5460 e_border_resize_limit(E_Border *bd,
5461                       int      *w,
5462                       int      *h)
5463 {
5464    double a;
5465
5466    E_OBJECT_CHECK(bd);
5467    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5468    *w -= bd->client_inset.l + bd->client_inset.r;
5469    *h -= bd->client_inset.t + bd->client_inset.b;
5470    if (*h < 1) *h = 1;
5471    if (*w < 1) *w = 1;
5472    if ((bd->client.icccm.base_w >= 0) &&
5473        (bd->client.icccm.base_h >= 0))
5474      {
5475         int tw, th;
5476
5477         tw = *w - bd->client.icccm.base_w;
5478         th = *h - bd->client.icccm.base_h;
5479         if (tw < 1) tw = 1;
5480         if (th < 1) th = 1;
5481         a = (double)(tw) / (double)(th);
5482         if ((bd->client.icccm.min_aspect != 0.0) &&
5483             (a < bd->client.icccm.min_aspect))
5484           {
5485              th = tw / bd->client.icccm.max_aspect;
5486              *h = th + bd->client.icccm.base_h;
5487           }
5488         else if ((bd->client.icccm.max_aspect != 0.0) &&
5489                  (a > bd->client.icccm.max_aspect))
5490           {
5491              tw = th * bd->client.icccm.max_aspect;
5492              *w = tw + bd->client.icccm.base_w;
5493           }
5494      }
5495    else
5496      {
5497         a = (double)*w / (double)*h;
5498         if ((bd->client.icccm.min_aspect != 0.0) &&
5499             (a < bd->client.icccm.min_aspect))
5500           *h = *w / bd->client.icccm.min_aspect;
5501         else if ((bd->client.icccm.max_aspect != 0.0) &&
5502                  (a > bd->client.icccm.max_aspect))
5503           *w = *h * bd->client.icccm.max_aspect;
5504      }
5505    if (bd->client.icccm.step_w > 0)
5506      {
5507         if (bd->client.icccm.base_w >= 0)
5508           *w = bd->client.icccm.base_w +
5509             (((*w - bd->client.icccm.base_w) / bd->client.icccm.step_w) *
5510              bd->client.icccm.step_w);
5511         else
5512           *w = bd->client.icccm.min_w +
5513             (((*w - bd->client.icccm.min_w) / bd->client.icccm.step_w) *
5514              bd->client.icccm.step_w);
5515      }
5516    if (bd->client.icccm.step_h > 0)
5517      {
5518         if (bd->client.icccm.base_h >= 0)
5519           *h = bd->client.icccm.base_h +
5520             (((*h - bd->client.icccm.base_h) / bd->client.icccm.step_h) *
5521              bd->client.icccm.step_h);
5522         else
5523           *h = bd->client.icccm.min_h +
5524             (((*h - bd->client.icccm.min_h) / bd->client.icccm.step_h) *
5525              bd->client.icccm.step_h);
5526      }
5527
5528    if (*h < 1) *h = 1;
5529    if (*w < 1) *w = 1;
5530
5531    if      (*w > bd->client.icccm.max_w) *w = bd->client.icccm.max_w;
5532    else if (*w < bd->client.icccm.min_w)
5533      *w = bd->client.icccm.min_w;
5534    if      (*h > bd->client.icccm.max_h) *h = bd->client.icccm.max_h;
5535    else if (*h < bd->client.icccm.min_h)
5536      *h = bd->client.icccm.min_h;
5537
5538    *w += bd->client_inset.l + bd->client_inset.r;
5539    *h += bd->client_inset.t + bd->client_inset.b;
5540 }
5541
5542 /* local subsystem functions */
5543 static void
5544 _e_border_free(E_Border *bd)
5545 {
5546 #ifdef _F_USE_DESK_WINDOW_PROFILE_
5547    const char *str;
5548 #endif
5549    if (bd->client.e.state.video_parent && bd->client.e.state.video_parent_border)
5550      {
5551         bd->client.e.state.video_parent_border->client.e.state.video_child =
5552           eina_list_remove
5553           (bd->client.e.state.video_parent_border->client.e.state.video_child,
5554               bd);
5555      }
5556    if (bd->client.e.state.video_child)
5557      {
5558         E_Border *tmp;
5559
5560         EINA_LIST_FREE(bd->client.e.state.video_child, tmp)
5561           {
5562              tmp->client.e.state.video_parent_border = NULL;
5563           }
5564      }
5565    if (bd->desktop)
5566      {
5567         efreet_desktop_free(bd->desktop);
5568         bd->desktop = NULL;
5569      }
5570    if (bd->post_job)
5571      {
5572         ecore_idle_enterer_del(bd->post_job);
5573         bd->post_job = NULL;
5574      }
5575    if (bd->pointer)
5576      {
5577         e_object_del(E_OBJECT(bd->pointer));
5578         bd->pointer = NULL;
5579      }
5580    if (bdresize == bd)
5581      _e_border_resize_end(bd);
5582    if (bdmove == bd)
5583      _e_border_move_end(bd);
5584    /* TODO: Other states to end before dying? */
5585
5586    if (bd->cur_mouse_action)
5587      {
5588         e_object_unref(E_OBJECT(bd->cur_mouse_action));
5589         bd->cur_mouse_action = NULL;
5590      }
5591
5592    E_FREE(bd->shape_rects);
5593    bd->shape_rects_num = 0;
5594 /*
5595    if (bd->dangling_ref_check)
5596      {
5597         ecore_timer_del(bd->dangling_ref_check);
5598         bd->dangling_ref_check = NULL;
5599      }
5600  */
5601    if (bd->kill_timer)
5602      {
5603         ecore_timer_del(bd->kill_timer);
5604         bd->kill_timer = NULL;
5605      }
5606    if (bd->ping_poller)
5607      {
5608         ecore_poller_del(bd->ping_poller);
5609         bd->ping_poller = NULL;
5610      }
5611    E_FREE_LIST(bd->pending_move_resize, free);
5612
5613    if (bd->shade.anim) ecore_animator_del(bd->shade.anim);
5614    if (bd->border_menu) e_menu_deactivate(bd->border_menu);
5615
5616    if (bd->border_locks_dialog)
5617      {
5618         e_object_del(E_OBJECT(bd->border_locks_dialog));
5619         bd->border_locks_dialog = NULL;
5620      }
5621    if (bd->border_remember_dialog)
5622      {
5623         e_object_del(E_OBJECT(bd->border_remember_dialog));
5624         bd->border_remember_dialog = NULL;
5625      }
5626    if (bd->border_border_dialog)
5627      {
5628         e_object_del(E_OBJECT(bd->border_border_dialog));
5629         bd->border_border_dialog = NULL;
5630      }
5631    if (bd->border_prop_dialog)
5632      {
5633         e_object_del(E_OBJECT(bd->border_prop_dialog));
5634         bd->border_prop_dialog = NULL;
5635      }
5636
5637    e_int_border_menu_del(bd);
5638
5639    if (focusing == bd)
5640      focusing = NULL;
5641
5642    focus_next = eina_list_remove(focus_next, bd);
5643    
5644    if ((focused == bd) ||
5645        (e_grabinput_last_focus_win_get() == bd->client.win))
5646      {
5647         if ((!focus_next) && (!focusing))
5648           {
5649              e_grabinput_focus(bd->zone->container->bg_win,
5650                                E_FOCUS_METHOD_PASSIVE);
5651              e_hints_active_window_set(bd->zone->container->manager, NULL);
5652           }
5653
5654         focused = NULL;
5655      }
5656    E_FREE_LIST(bd->handlers, ecore_event_handler_del);
5657    if (bd->remember)
5658      {
5659         E_Remember *rem;
5660
5661         rem = bd->remember;
5662         bd->remember = NULL;
5663         e_remember_unuse(rem);
5664      }
5665    if (!bd->already_unparented)
5666      {
5667         ecore_x_window_reparent(bd->client.win, bd->zone->container->manager->root,
5668                                 bd->x + bd->client_inset.l, bd->y + bd->client_inset.t);
5669         ecore_x_window_save_set_del(bd->client.win);
5670         bd->already_unparented = 1;
5671      }
5672    if (bd->group) eina_list_free(bd->group);
5673    if (bd->transients) eina_list_free(bd->transients);
5674    if (bd->stick_desks) eina_list_free(bd->stick_desks);
5675    if (bd->client.netwm.icons)
5676      {
5677         int i;
5678         for (i = 0; i < bd->client.netwm.num_icons; i++)
5679           free(bd->client.netwm.icons[i].data);
5680         free(bd->client.netwm.icons);
5681      }
5682    if (bd->client.netwm.extra_types)
5683      free(bd->client.netwm.extra_types);
5684    if (bd->client.border.name)
5685      eina_stringshare_del(bd->client.border.name);
5686    if (bd->bordername)
5687      eina_stringshare_del(bd->bordername);
5688    if (bd->client.icccm.name)
5689      eina_stringshare_del(bd->client.icccm.name);
5690    if (bd->client.icccm.class)
5691      {
5692         if (!strcmp(bd->client.icccm.class, "Vmplayer"))
5693           e_bindings_mapping_change_enable(EINA_TRUE);
5694         eina_stringshare_del(bd->client.icccm.class);
5695      }
5696    if (bd->client.icccm.title)
5697      eina_stringshare_del(bd->client.icccm.title);
5698    if (bd->client.icccm.icon_name)
5699      eina_stringshare_del(bd->client.icccm.icon_name);
5700    if (bd->client.icccm.machine)
5701      eina_stringshare_del(bd->client.icccm.machine);
5702    if (bd->client.icccm.window_role)
5703      eina_stringshare_del(bd->client.icccm.window_role);
5704
5705    if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
5706      {
5707         int i;
5708
5709         for (i = 0; i < bd->client.icccm.command.argc; i++)
5710           free(bd->client.icccm.command.argv[i]);
5711         free(bd->client.icccm.command.argv);
5712      }
5713    if (bd->client.netwm.name)
5714      eina_stringshare_del(bd->client.netwm.name);
5715    if (bd->client.netwm.icon_name)
5716      eina_stringshare_del(bd->client.netwm.icon_name);
5717    e_object_del(E_OBJECT(bd->shape));
5718    if (bd->internal_icon) eina_stringshare_del(bd->internal_icon);
5719    if (bd->internal_icon_key) eina_stringshare_del(bd->internal_icon_key);
5720    if (bd->icon_object) evas_object_del(bd->icon_object);
5721 #ifdef _F_USE_DESK_WINDOW_PROFILE_
5722    EINA_LIST_FREE(bd->client.e.state.profiles, str)
5723      {
5724         if (str) eina_stringshare_del(str);
5725      }
5726    bd->client.e.state.profiles = NULL;
5727    if (bd->client.e.state.profile)
5728      eina_stringshare_del(bd->client.e.state.profile);
5729    bd->client.e.state.profile = NULL;
5730 #endif
5731 #ifdef _F_ZONE_WINDOW_ROTATION_
5732    if (e_config->wm_win_rotation)
5733      {
5734         bd->client.e.fetch.rot.app_set = 0;
5735         bd->client.e.state.rot.preferred_rot = -1;
5736
5737         if (bd->client.e.state.rot.available_rots)
5738           E_FREE(bd->client.e.state.rot.available_rots);
5739
5740         _e_border_rotation_list_remove(bd);
5741         if ((rot.vkbd) && (rot.vkbd == bd))
5742           {
5743              ELB(ELBT_BD, "UNSET VKBD", bd->client.win);
5744              rot.vkbd = NULL;
5745              if (rot.vkbd_ctrl_win)
5746                {
5747                   ELB(ELBT_BD, "SET KBD_OFF", 0);
5748                   ecore_x_e_virtual_keyboard_state_set
5749                     (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
5750                }
5751
5752              rot.vkbd_hide_prepare_done = EINA_FALSE;
5753              if (rot.vkbd_hide_prepare_timer)
5754                ecore_timer_del(rot.vkbd_hide_prepare_timer);
5755              rot.vkbd_hide_prepare_timer = NULL;
5756              if (rot.vkbd_hide_timer)
5757                ecore_timer_del(rot.vkbd_hide_timer);
5758              rot.vkbd_hide_timer = NULL;
5759
5760              rot.vkbd_show_prepare_done = EINA_FALSE;
5761              if (rot.vkbd_show_prepare_timer)
5762                ecore_timer_del(rot.vkbd_show_prepare_timer);
5763              rot.vkbd_show_prepare_timer = NULL;
5764              if (rot.vkbd_show_timer)
5765                ecore_timer_del(rot.vkbd_show_timer);
5766              rot.vkbd_show_timer = NULL;
5767           }
5768         else if ((rot.vkbd_prediction) &&
5769                  (rot.vkbd_prediction == bd))
5770           rot.vkbd_prediction = NULL;
5771      }
5772 #endif
5773 #ifdef _F_DEICONIFY_APPROVE_
5774    if (bd->client.e.state.deiconify_approve.pending_job)
5775      {
5776         ecore_job_del(bd->client.e.state.deiconify_approve.pending_job);
5777         bd->client.e.state.deiconify_approve.pending_job = NULL;
5778      }
5779 #endif
5780    evas_object_del(bd->bg_object);
5781    e_canvas_del(bd->bg_ecore_evas);
5782    ecore_evas_free(bd->bg_ecore_evas);
5783    ecore_x_window_free(bd->client.shell_win);
5784    e_focus_setdown(bd);
5785    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5786    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5787    ecore_x_window_free(bd->win);
5788
5789    eina_hash_del(borders_hash, e_util_winid_str_get(bd->client.win), bd);
5790    eina_hash_del(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
5791    eina_hash_del(borders_hash, e_util_winid_str_get(bd->win), bd);
5792    borders = eina_list_remove(borders, bd);
5793    focus_stack = eina_list_remove(focus_stack, bd);
5794    raise_stack = eina_list_remove(raise_stack, bd);
5795
5796    e_container_border_remove(bd);
5797    free(bd);
5798 }
5799
5800 /*
5801    static int
5802    _e_border_del_dangling_ref_check(void *data)
5803    {
5804    E_Border *bd;
5805
5806    bd = data;
5807    printf("---\n");
5808    printf("EEK EEK border still around 1 second after being deleted!\n");
5809    printf("%p, %i, \"%s\" [\"%s\" \"%s\"]\n",
5810           bd, e_object_ref_get(E_OBJECT(bd)), bd->client.icccm.title,
5811           bd->client.icccm.name, bd->client.icccm.class);
5812    //   e_object_breadcrumb_debug(E_OBJECT(bd));
5813    printf("---\n");
5814    return 1;
5815    }
5816  */
5817
5818 static void
5819 _e_border_del(E_Border *bd)
5820 {
5821    E_Event_Border_Remove *ev;
5822    E_Border *child;
5823
5824 #ifdef _F_BORDER_HOOK_PATCH_
5825    _e_border_hook_call(E_BORDER_HOOK_DEL_BORDER, bd);
5826 #endif
5827
5828    if (bd == focused)
5829      {
5830         focused = NULL;
5831      }
5832
5833    if (bd == focusing)
5834      focusing = NULL;
5835
5836    focus_next = eina_list_remove(focus_next, bd);
5837
5838    if (bd->fullscreen) bd->desk->fullscreen_borders--;
5839
5840    if ((drag_border) && (drag_border->data == bd))
5841      {
5842         e_object_del(E_OBJECT(drag_border));
5843         drag_border = NULL;
5844      }
5845    if (bd->border_menu) e_menu_deactivate(bd->border_menu);
5846
5847    if (bd->border_locks_dialog)
5848      {
5849         e_object_del(E_OBJECT(bd->border_locks_dialog));
5850         bd->border_locks_dialog = NULL;
5851      }
5852    if (bd->border_remember_dialog)
5853      {
5854         e_object_del(E_OBJECT(bd->border_remember_dialog));
5855         bd->border_remember_dialog = NULL;
5856      }
5857    if (bd->border_border_dialog)
5858      {
5859         e_object_del(E_OBJECT(bd->border_border_dialog));
5860         bd->border_border_dialog = NULL;
5861      }
5862    if (bd->border_prop_dialog)
5863      {
5864         e_object_del(E_OBJECT(bd->border_prop_dialog));
5865         bd->border_prop_dialog = NULL;
5866      }
5867
5868    e_int_border_menu_del(bd);
5869
5870    if (bd->raise_timer)
5871      {
5872         ecore_timer_del(bd->raise_timer);
5873         bd->raise_timer = NULL;
5874      }
5875    if (!bd->already_unparented)
5876      {
5877         ecore_x_window_reparent(bd->client.win,
5878                                 bd->zone->container->manager->root,
5879                                 bd->x + bd->client_inset.l,
5880                                 bd->y + bd->client_inset.t);
5881         ecore_x_window_save_set_del(bd->client.win);
5882         bd->already_unparented = 1;
5883 //      bd->client.win = 0;
5884      }
5885    bd->already_unparented = 1;
5886
5887    if ((!bd->new_client) && (!stopping))
5888      {
5889         ev = E_NEW(E_Event_Border_Remove, 1);
5890         ev->border = bd;
5891         e_object_ref(E_OBJECT(bd));
5892         // e_object_breadcrumb_add(E_OBJECT(bd), "border_remove_event");
5893         ecore_event_add(E_EVENT_BORDER_REMOVE, ev, _e_border_event_border_remove_free, NULL);
5894      }
5895
5896    if (bd->parent)
5897      {
5898         bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
5899         if (bd->parent->modal == bd)
5900           {
5901              ecore_x_event_mask_unset(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
5902              ecore_x_event_mask_set(bd->parent->client.win, bd->parent->saved.event_mask);
5903              bd->parent->lock_close = 0;
5904              bd->parent->saved.event_mask = 0;
5905              bd->parent->modal = NULL;
5906           }
5907         bd->parent = NULL;
5908      }
5909    EINA_LIST_FREE(bd->transients, child)
5910      {
5911         child->parent = NULL;
5912      }
5913
5914 #ifdef _F_DEICONIFY_APPROVE_
5915    bd->client.e.state.deiconify_approve.render_done = 0;
5916
5917    E_Border *ancestor_bd;
5918    ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
5919    if ((ancestor_bd) &&
5920        (!e_object_is_del(E_OBJECT(ancestor_bd))))
5921      {
5922         ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
5923         bd->client.e.state.deiconify_approve.ancestor = NULL;
5924
5925         if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
5926             (ancestor_bd->client.e.state.deiconify_approve.render_done))
5927           {
5928              if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
5929                {
5930                   ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
5931                   ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
5932                   e_border_uniconify(ancestor_bd);
5933                }
5934           }
5935      }
5936
5937    if (bd->client.e.state.deiconify_approve.wait_timer)
5938      {
5939         ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer);
5940         bd->client.e.state.deiconify_approve.wait_timer = NULL;
5941      }
5942
5943    if (bd->client.e.state.deiconify_approve.pending_job)
5944      {
5945         ecore_job_del(bd->client.e.state.deiconify_approve.pending_job);
5946         bd->client.e.state.deiconify_approve.pending_job = NULL;
5947      }
5948
5949    if (bd->client.e.state.deiconify_approve.req_list)
5950      {
5951         EINA_LIST_FREE(bd->client.e.state.deiconify_approve.req_list, child)
5952           {
5953              child->client.e.state.deiconify_approve.render_done = 0;
5954              child->client.e.state.deiconify_approve.ancestor = NULL;
5955           }
5956      }
5957 #endif
5958
5959 #ifdef _F_ZONE_WINDOW_ROTATION_
5960    if (rot.list) _e_border_rotation_list_remove(bd);
5961    if (rot.async_list)
5962      {
5963         Eina_List *l;
5964         E_Border_Rotation_Info *info = NULL;
5965
5966         EINA_LIST_FOREACH(rot.async_list, l, info)
5967            if (info->bd == bd)
5968              {
5969                 rot.async_list = eina_list_remove(rot.async_list, info);
5970                 E_FREE(info);
5971              }
5972      }
5973 #endif
5974
5975    if (bd->leader)
5976      {
5977         bd->leader->group = eina_list_remove(bd->leader->group, bd);
5978         if (bd->leader->modal == bd)
5979           bd->leader->modal = NULL;
5980         bd->leader = NULL;
5981      }
5982    EINA_LIST_FREE(bd->group, child)
5983      {
5984         child->leader = NULL;
5985      }
5986 }
5987
5988 #ifdef PRINT_LOTS_OF_DEBUG
5989 static void
5990 _e_border_print(E_Border   *bd,
5991                 const char *func)
5992 {
5993    if (!bd) return;
5994
5995    DBG("*Window Info*"
5996           "\tPointer: %p\n"
5997           "\tName: %s\n"
5998           "\tTitle: %s\n"
5999           "\tBorderless: %s\n",
6000           bd, bd->client.icccm.name, bd->client.icccm.title,
6001           bd->borderless ? "TRUE" : "FALSE");
6002 }
6003
6004 #endif
6005
6006 static Eina_Bool
6007 _e_border_cb_window_show_request(void *data  __UNUSED__,
6008                                  int ev_type __UNUSED__,
6009                                  void       *ev)
6010 {
6011    E_Border *bd;
6012    E_Container *con;
6013    Ecore_X_Event_Window_Show_Request *e;
6014
6015    e = ev;
6016    bd = e_border_find_by_client_window(e->win);
6017    if (!bd) return ECORE_CALLBACK_PASS_ON;
6018
6019 #ifdef _F_ZONE_WINDOW_ROTATION_
6020    if ((e_config->wm_win_rotation) &&
6021        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
6022        (bd == rot.vkbd) &&
6023        (rot.vkbd_hide_prepare_timer))
6024      {
6025         con = bd->zone->container;
6026         bd = e_border_new(con, e->win, 0, 0);
6027      }
6028 #endif
6029
6030    if (bd->iconic)
6031      {
6032         if (!bd->lock_client_iconify)
6033           e_border_uniconify(bd);
6034      }
6035    else
6036      {
6037         /* FIXME: make border "urgent" for a bit - it wants attention */
6038 /*      e_border_show(bd); */
6039           if (!bd->lock_client_stacking)
6040             e_border_raise(bd);
6041      }
6042    return ECORE_CALLBACK_PASS_ON;
6043 }
6044
6045 static Eina_Bool
6046 _e_border_cb_window_destroy(void *data  __UNUSED__,
6047                             int ev_type __UNUSED__,
6048                             void       *ev)
6049 {
6050    E_Border *bd;
6051    Ecore_X_Event_Window_Destroy *e;
6052
6053    e = ev;
6054    bd = e_border_find_by_client_window(e->win);
6055    if (!bd) return ECORE_CALLBACK_PASS_ON;
6056    ELB(ELBT_BD, "X_WIN_DEL", bd->client.win);
6057 #ifdef _F_ZONE_WINDOW_ROTATION_
6058    if (e_config->wm_win_rotation)
6059      {
6060         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
6061           {
6062              ELB(ELBT_BD, "X_DEL_NOTIFY", bd->client.win);
6063              if (!rot.vkbd_hide_prepare_timer)
6064                {
6065                   ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
6066                   e_border_hide(bd, 0);
6067                   if (!rot.vkbd_hide_prepare_timer)
6068                     {
6069                        ELB(ELBT_BD, "DEL VKBD", bd->client.win);
6070                        e_object_del(E_OBJECT(bd));
6071                     }
6072                }
6073              return ECORE_CALLBACK_PASS_ON;
6074           }
6075      }
6076 #endif
6077
6078 #ifdef _F_DEICONIFY_APPROVE_
6079    if (e_config->deiconify_approve)
6080      {
6081         if (bd->client.e.state.pending_event.pending)
6082           {
6083              bd->client.e.state.pending_event.destroy.pending = 1;
6084              bd->client.e.state.pending_event.destroy.win = e->win;
6085              bd->client.e.state.pending_event.destroy.event_win = e->event_win;
6086              ELB(ELBT_BD, "PENDING destroy event", bd->client.win);
6087              return ECORE_CALLBACK_CANCEL;
6088           }
6089      }
6090
6091    ELB(ELBT_BD, "Real Destroy", bd->client.win);
6092 #endif
6093
6094    e_border_hide(bd, 0);
6095    e_object_del(E_OBJECT(bd));
6096    return ECORE_CALLBACK_PASS_ON;
6097 }
6098
6099 #ifdef _F_DEICONIFY_APPROVE_
6100 static E_Border *
6101 _e_border_find_below_win(E_Border* bd)
6102 {
6103    Eina_List *l;
6104    int i, pos;
6105    Eina_Bool passed;
6106    E_Border *temp_bd;
6107    E_Border *below_bd;
6108
6109    passed = EINA_FALSE;
6110    below_bd = NULL;
6111
6112    E_Border_List *bl;
6113    bl = e_container_border_list_last(bd->zone->container);
6114    while ((temp_bd = e_container_border_list_prev(bl)))
6115      {
6116         /* skip if it's the same border */
6117         if (temp_bd == bd)
6118           {
6119              passed = EINA_TRUE;
6120              continue;
6121           }
6122
6123         if (e_object_is_del(E_OBJECT(temp_bd))) continue;
6124
6125         /* skip if it's not on this zone */
6126         if (temp_bd->zone != bd->zone) continue;
6127
6128         if (E_CONTAINS(temp_bd->x, temp_bd->y, temp_bd->w, temp_bd->h, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
6129           {
6130              if (!temp_bd->client.argb && temp_bd->visible)
6131                {
6132                   below_bd = NULL;
6133                   break;
6134                }
6135           }
6136
6137         if (!passed) continue;
6138
6139         if ((!temp_bd->client.argb) &&
6140             (temp_bd->x == temp_bd->zone->x) &&
6141             (temp_bd->y == temp_bd->zone->y) &&
6142             (temp_bd->w == temp_bd->zone->w) &&
6143             (temp_bd->h == temp_bd->zone->h))
6144           {
6145              if (temp_bd->visible)
6146                {
6147                   below_bd = NULL;
6148                   break;
6149                }
6150
6151              if (ecore_x_window_visible_get(temp_bd->client.win))
6152                {
6153                   below_bd = temp_bd;
6154                   break;
6155                }
6156           }
6157      }
6158    e_container_border_list_free(bl);
6159
6160    return below_bd;
6161 }
6162 #endif
6163
6164 static Eina_Bool
6165 _e_border_cb_window_hide(void *data  __UNUSED__,
6166                          int ev_type __UNUSED__,
6167                          void       *ev)
6168 {
6169    E_Border *bd = NULL;
6170    Ecore_X_Event_Window_Hide *e;
6171
6172    e = ev;
6173 //   printf("HIDE: %x, event %x send: %i\n", e->win, e->event_win, e->send_event);
6174 // not interested in hide events from windows other than the window in question
6175    if (e->win != e->event_win)
6176      {
6177         bd = e_border_find_by_client_window(e->win);
6178         if (!bd) return ECORE_CALLBACK_PASS_ON;
6179         if (!e->send_event) return ECORE_CALLBACK_PASS_ON;
6180         else
6181           {
6182              if (!((bd->zone) &&
6183                    (bd->zone->container->manager->root == e->event_win)))
6184                return ECORE_CALLBACK_PASS_ON;
6185           }
6186      }
6187    if (!bd) bd = e_border_find_by_client_window(e->win);
6188 //   printf("  bd = %p\n", bd);
6189    if (!bd)
6190      {
6191         if (ecore_x_window_visible_get(e->win))
6192           {
6193              ELB(ELBT_BD, "FORCE UNMAP client window", e->win);
6194              ecore_x_window_hide(e->win);
6195           }
6196         return ECORE_CALLBACK_PASS_ON;
6197      }
6198
6199 #ifdef _F_DEICONIFY_APPROVE_
6200    if (e_config->deiconify_approve)
6201      {
6202         if (bd->client.e.state.pending_event.done)
6203            goto do_hide;
6204
6205         if (bd->client.e.state.pending_event.pending)
6206           {
6207              return ECORE_CALLBACK_CANCEL;
6208           }
6209
6210         if (!E_CONTAINS(bd->x, bd->y, bd->w, bd->h, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
6211            goto do_hide;
6212
6213         E_Border *below_bd;
6214         // 1. find below non-alpha full size win
6215         below_bd = _e_border_find_below_win(bd);
6216
6217         if (below_bd)
6218           {
6219              // 2. check those rotation
6220              bd->client.e.state.pending_event.pending = 1;
6221              bd->client.e.state.pending_event.hold_bd = below_bd;
6222
6223              bd->client.e.state.pending_event.hide.pending = 1;
6224              bd->client.e.state.pending_event.hide.win = e->win;
6225              bd->client.e.state.pending_event.hide.event_win = e->event_win;
6226              bd->client.e.state.pending_event.hide.send_event = e->send_event;
6227
6228              below_bd->client.e.state.deiconify_approve.pending_bd = bd;
6229              ELBF(ELBT_ROT, 0, bd->client.win, "below_win:%x, below_win's wait_bd:%x", below_bd->client.win, below_bd->client.e.state.deiconify_approve.pending_bd->client.win);
6230
6231              // 3. if not same then uniconify
6232              e_border_uniconify(below_bd);
6233
6234              ELB(ELBT_BD, "PENDING hide event", bd->client.win);
6235              return ECORE_CALLBACK_CANCEL;
6236           }
6237      }
6238
6239 do_hide:
6240    bd->client.e.state.pending_event.done = 0;
6241    bd->client.e.state.pending_event.pending = 0;
6242    ELB(ELBT_BD, "Real hide", bd->client.win);
6243 #endif
6244
6245 //   printf("  bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap);
6246    if (bd->ignore_first_unmap > 0)
6247      {
6248         bd->ignore_first_unmap--;
6249         return ECORE_CALLBACK_PASS_ON;
6250      }
6251    /* Don't delete hidden or iconified windows */
6252 #ifdef _F_USE_EXTENDED_ICONIFY_
6253    if (bd->await_hide_event > 0)
6254 #else
6255    if ((bd->iconic) || (bd->await_hide_event > 0))
6256 #endif
6257      {
6258 //        printf("  Don't delete hidden or iconified windows\n");
6259 //        printf("  bd->iconic = %i, bd->visible = %i, bd->new_client = %i, bd->await_hide_event = %i\n",
6260 //               bd->iconic, bd->visible, bd->new_client, bd->await_hide_event);
6261         if (bd->await_hide_event > 0)
6262           {
6263              bd->await_hide_event--;
6264           }
6265         else
6266           {
6267 //             printf("  hide really\n");
6268              /* Only hide the border if it is visible */
6269              if (bd->visible) e_border_hide(bd, 1);
6270           }
6271      }
6272    else
6273      {
6274 //             printf("  hide2\n");
6275 #ifdef _F_USE_EXTENDED_ICONIFY_
6276         if (bd->iconic)
6277           {
6278              bd->iconic = 0;
6279              bd->visible = 1;
6280           }
6281 #endif
6282
6283 #ifdef _F_ZONE_WINDOW_ROTATION_
6284         if (e_config->wm_win_rotation)
6285           {
6286              if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
6287                {
6288                   ELB(ELBT_BD, "X_UNMAP_NOTIFY", bd->client.win);
6289                   if (!rot.vkbd_hide_prepare_timer)
6290                     {
6291                        ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
6292                        e_border_hide(bd, 0);
6293                        if (!rot.vkbd_hide_prepare_timer)
6294                          {
6295                             ELB(ELBT_BD, "DEL VKBD", bd->client.win);
6296                             e_object_del(E_OBJECT(bd));
6297                          }
6298                     }
6299                   return ECORE_CALLBACK_PASS_ON;
6300                }
6301           }
6302 #endif
6303         e_border_hide(bd, 0);
6304         e_object_del(E_OBJECT(bd));
6305      }
6306    return ECORE_CALLBACK_PASS_ON;
6307 }
6308
6309 static Eina_Bool
6310 _e_border_cb_window_reparent(void *data  __UNUSED__,
6311                              int ev_type __UNUSED__,
6312                              void *ev    __UNUSED__)
6313 {
6314 #if 0
6315    E_Border *bd;
6316    Ecore_X_Event_Window_Reparent *e;
6317
6318    e = ev;
6319    bd = e_border_find_by_client_window(e->win);
6320    if (!bd) return 1;
6321    if (e->parent == bd->client.shell_win) return 1;
6322    if (ecore_x_window_parent_get(e->win) == bd->client.shell_win)
6323      {
6324         return 1;
6325      }
6326    e_border_hide(bd, 0);
6327    e_object_del(E_OBJECT(bd));
6328 #endif
6329    return ECORE_CALLBACK_PASS_ON;
6330 }
6331
6332 static Eina_Bool
6333 _e_border_cb_window_configure_request(void *data  __UNUSED__,
6334                                       int ev_type __UNUSED__,
6335                                       void       *ev)
6336 {
6337    E_Border *bd;
6338    Ecore_X_Event_Window_Configure_Request *e;
6339
6340    e = ev;
6341    bd = e_border_find_by_client_window(e->win);
6342    if (!bd)
6343      {
6344         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6345         if (!e_util_container_window_find(e->win))
6346           ecore_x_window_configure(e->win, e->value_mask,
6347                                    e->x, e->y, e->w, e->h, e->border,
6348                                    e->abovewin, e->detail);
6349         return ECORE_CALLBACK_PASS_ON;
6350      }
6351
6352    if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
6353        (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
6354      {
6355         int x, y;
6356
6357         x = bd->x;
6358         y = bd->y;
6359         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
6360           x = e->x;
6361         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
6362           y = e->y;
6363         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6364             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6365           {
6366              int w, h;
6367
6368              h = bd->h;
6369              w = bd->w;
6370              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6371                w = e->w + bd->client_inset.l + bd->client_inset.r;
6372              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6373                h = e->h + bd->client_inset.t + bd->client_inset.b;
6374              if ((!bd->lock_client_location) && (!bd->lock_client_size))
6375                {
6376                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6377                     {
6378                        bd->saved.x = x - bd->zone->x;
6379                        bd->saved.y = y - bd->zone->y;
6380                        bd->saved.w = w;
6381                        bd->saved.h = h;
6382                     }
6383                   else
6384                     e_border_move_resize(bd, x, y, w, h);
6385                }
6386              else if (!bd->lock_client_location)
6387                {
6388                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6389                     {
6390                        bd->saved.x = x - bd->zone->x;
6391                        bd->saved.y = y - bd->zone->y;
6392                     }
6393                   else
6394                     e_border_move(bd, x, y);
6395                }
6396              else if (!bd->lock_client_size)
6397                {
6398                   if ((bd->shaded) || (bd->shading))
6399                     {
6400                        int pw, ph;
6401
6402                        pw = bd->client.w;
6403                        ph = bd->client.h;
6404                        if ((bd->shade.dir == E_DIRECTION_UP) ||
6405                            (bd->shade.dir == E_DIRECTION_DOWN))
6406                          {
6407                             e_border_resize(bd, w, bd->h);
6408                             bd->client.h = ph;
6409                          }
6410                        else
6411                          {
6412                             e_border_resize(bd, bd->w, h);
6413                             bd->client.w = pw;
6414                          }
6415                     }
6416                   else
6417                     {
6418                        if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6419                          {
6420                             bd->saved.w = w;
6421                             bd->saved.h = h;
6422                          }
6423                        else
6424                          e_border_resize(bd, w, h);
6425                     }
6426                }
6427           }
6428         else
6429           {
6430              if (!bd->lock_client_location)
6431                {
6432                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6433                     {
6434                        bd->saved.x = x - bd->zone->x;
6435                        bd->saved.y = y - bd->zone->y;
6436                     }
6437                   else
6438                     e_border_move(bd, x, y);
6439                }
6440           }
6441      }
6442    else if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6443             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6444      {
6445         int w, h;
6446
6447         h = bd->h;
6448         w = bd->w;
6449         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6450           w = e->w + bd->client_inset.l + bd->client_inset.r;
6451         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6452           h = e->h + bd->client_inset.t + bd->client_inset.b;
6453 #ifdef _F_ZONE_WINDOW_ROTATION_
6454         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
6455 #endif
6456         if (!bd->lock_client_size)
6457           {
6458              if ((bd->shaded) || (bd->shading))
6459                {
6460                   int pw, ph;
6461
6462                   pw = bd->client.w;
6463                   ph = bd->client.h;
6464                   if ((bd->shade.dir == E_DIRECTION_UP) ||
6465                       (bd->shade.dir == E_DIRECTION_DOWN))
6466                     {
6467                        e_border_resize(bd, w, bd->h);
6468                        bd->client.h = ph;
6469                     }
6470                   else
6471                     {
6472                        e_border_resize(bd, bd->w, h);
6473                        bd->client.w = pw;
6474                     }
6475                }
6476              else
6477                {
6478                   if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE)
6479                     {
6480                        int zx, zy, zw, zh;
6481                        int rx = bd->x;
6482                        int ry = bd->y;
6483                        zx = zy = zw = zh = 0;
6484
6485      /*
6486       * This code does resize and move a window on a
6487       * X configure request into an useful geometry.
6488       * This is really useful for size jumping file dialogs.
6489       */
6490
6491                        if (bd->zone)
6492                          {
6493                             e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
6494
6495                             if (e_config->geometry_auto_resize_limit == 1)
6496                               {
6497                                  if (w > zw)
6498                                    w = zw;
6499
6500                                  if (h > zh)
6501                                    h = zh;
6502                               }
6503                          }
6504                        e_border_resize(bd, w, h);
6505
6506                        if (e_config->geometry_auto_move == 1)
6507                          {
6508                              /* z{x,y,w,h} are only set here; FIXME! */
6509                              if (bd->zone)
6510                                {
6511                                   // move window horizontal if resize to not useful geometry
6512                                   if (bd->x + bd->w > zx + zw)
6513                                     rx = zx + zw - bd->w;
6514                                   else if (bd->x < zx)
6515                                     rx = zx;
6516
6517                                   // move window vertical if resize to not useful geometry
6518                                   if (bd->y + bd->h > zy + zh)
6519                                     ry = zy + zh - bd->h;
6520                                   else if (bd->y < zy)
6521                                     ry = zy;
6522                                }
6523                              e_border_move(bd, rx, ry);
6524                          }
6525                     }
6526                }
6527           }
6528      }
6529    if (!bd->lock_client_stacking)
6530      {
6531         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
6532             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
6533           {
6534              E_Border *obd;
6535
6536              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6537                {
6538                   obd = e_border_find_by_client_window(e->abovewin);
6539                   if (obd)
6540                     {
6541                        e_border_stack_above(bd, obd);
6542                     }
6543                   else
6544                     {
6545                        ecore_x_window_configure(bd->win,
6546                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6547                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6548                                                 0, 0, 0, 0, 0,
6549                                                 e->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
6550                        /* FIXME: need to rebuiuld border list from current stacking */
6551                     }
6552                }
6553              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6554                {
6555                   obd = e_border_find_by_client_window(e->abovewin);
6556                   if (obd)
6557                     {
6558                        e_border_stack_below(bd, obd);
6559                     }
6560                   else
6561                     {
6562                        ecore_x_window_configure(bd->win,
6563                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6564                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6565                                                 0, 0, 0, 0, 0,
6566                                                 e->abovewin, ECORE_X_WINDOW_STACK_BELOW);
6567                        /* FIXME: need to rebuiuld border list from current stacking */
6568                     }
6569                }
6570              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6571                {
6572      /* FIXME: do */
6573                }
6574              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6575                {
6576      /* FIXME: do */
6577                }
6578              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6579                {
6580      /* FIXME: do */
6581                }
6582           }
6583         else if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
6584           {
6585              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6586                {
6587                   e_border_raise(bd);
6588                }
6589              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6590                {
6591                   e_border_lower(bd);
6592                }
6593              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6594                {
6595      /* FIXME: do */
6596                }
6597              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6598                {
6599      /* FIXME: do */
6600                }
6601              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6602                {
6603      /* FIXME: do */
6604                }
6605           }
6606      }
6607
6608    /* FIXME: need to send synthetic stacking event too as well as move/resize */
6609    _e_border_client_move_resize_send(bd);
6610    return ECORE_CALLBACK_PASS_ON;
6611 }
6612
6613 static Eina_Bool
6614 _e_border_cb_window_resize_request(void *data  __UNUSED__,
6615                                    int ev_type __UNUSED__,
6616                                    void       *ev)
6617 {
6618    E_Border *bd;
6619    Ecore_X_Event_Window_Resize_Request *e;
6620
6621    e = ev;
6622    bd = e_border_find_by_client_window(e->win);
6623    if (!bd)
6624      {
6625         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6626         ecore_x_window_resize(e->win, e->w, e->h);
6627         return ECORE_CALLBACK_PASS_ON;
6628      }
6629    {
6630       int w, h;
6631
6632       w = e->w + bd->client_inset.l + bd->client_inset.r;
6633       h = e->h + bd->client_inset.t + bd->client_inset.b;
6634       if ((bd->shaded) || (bd->shading))
6635         {
6636            int pw, ph;
6637
6638            pw = bd->client.w;
6639            ph = bd->client.h;
6640            if ((bd->shade.dir == E_DIRECTION_UP) ||
6641                (bd->shade.dir == E_DIRECTION_DOWN))
6642              {
6643                 e_border_resize(bd, w, bd->h);
6644                 bd->client.h = ph;
6645              }
6646            else
6647              {
6648                 e_border_resize(bd, bd->w, h);
6649                 bd->client.w = pw;
6650              }
6651         }
6652       else
6653         e_border_resize(bd, w, h);
6654    }
6655
6656    _e_border_client_move_resize_send(bd);
6657    return ECORE_CALLBACK_PASS_ON;
6658 }
6659
6660 static Eina_Bool
6661 _e_border_cb_window_gravity(void *data  __UNUSED__,
6662                             int ev_type __UNUSED__,
6663                             void *ev    __UNUSED__)
6664 {
6665 //   E_Border *bd;
6666 //   Ecore_X_Event_Window_Gravity *e;
6667
6668 //   e = ev;
6669 //   bd = e_border_find_by_client_window(e->win);
6670 //   if (!bd) return 1;
6671              return 1;
6672 }
6673
6674 static Eina_Bool
6675 _e_border_cb_window_stack_request(void *data  __UNUSED__,
6676                                   int ev_type __UNUSED__,
6677                                   void       *ev)
6678 {
6679    E_Border *bd;
6680    Ecore_X_Event_Window_Stack_Request *e;
6681
6682    e = ev;
6683    bd = e_border_find_by_client_window(e->win);
6684    if (!bd)
6685      {
6686         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6687         if (!e_util_container_window_find(e->win))
6688           {
6689              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6690                ecore_x_window_raise(e->win);
6691              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6692                ecore_x_window_lower(e->win);
6693           }
6694         return ECORE_CALLBACK_PASS_ON;
6695      }
6696    if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6697      e_border_raise(bd);
6698    else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6699      e_border_lower(bd);
6700    return ECORE_CALLBACK_PASS_ON;
6701 }
6702
6703 static Eina_Bool
6704 _e_border_cb_window_property(void *data  __UNUSED__,
6705                              int ev_type __UNUSED__,
6706                              void       *ev)
6707 {
6708    E_Border *bd;
6709    Ecore_X_Event_Window_Property *e;
6710
6711    e = ev;
6712    bd = e_border_find_by_client_window(e->win);
6713    if (!bd) return ECORE_CALLBACK_PASS_ON;
6714    if (e->atom == ECORE_X_ATOM_WM_NAME)
6715      {
6716         if ((!bd->client.netwm.name) &&
6717             (!bd->client.netwm.fetch.name))
6718           {
6719              bd->client.icccm.fetch.title = 1;
6720              bd->changed = 1;
6721           }
6722      }
6723    else if (e->atom == ECORE_X_ATOM_NET_WM_NAME)
6724      {
6725         bd->client.netwm.fetch.name = 1;
6726         bd->changed = 1;
6727      }
6728    else if (e->atom == ECORE_X_ATOM_WM_CLASS)
6729      {
6730         bd->client.icccm.fetch.name_class = 1;
6731         bd->changed = 1;
6732      }
6733    else if (e->atom == ECORE_X_ATOM_WM_ICON_NAME)
6734      {
6735         if ((!bd->client.netwm.icon_name) &&
6736             (!bd->client.netwm.fetch.icon_name))
6737           {
6738              bd->client.icccm.fetch.icon_name = 1;
6739              bd->changed = 1;
6740           }
6741      }
6742    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
6743      {
6744         bd->client.netwm.fetch.icon_name = 1;
6745         bd->changed = 1;
6746      }
6747    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
6748      {
6749         bd->client.icccm.fetch.machine = 1;
6750         bd->changed = 1;
6751      }
6752    else if (e->atom == ECORE_X_ATOM_WM_PROTOCOLS)
6753      {
6754         bd->client.icccm.fetch.protocol = 1;
6755         bd->changed = 1;
6756      }
6757    else if (e->atom == ECORE_X_ATOM_WM_HINTS)
6758      {
6759         bd->client.icccm.fetch.hints = 1;
6760         bd->changed = 1;
6761      }
6762    else if (e->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
6763      {
6764         bd->client.icccm.fetch.size_pos_hints = 1;
6765         bd->changed = 1;
6766      }
6767    else if (e->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
6768      {
6769         /*
6770            if ((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN) &&
6771             (!bd->client.netwm.fetch.type))
6772            {
6773          */
6774           bd->client.mwm.fetch.hints = 1;
6775           bd->changed = 1;
6776           /*
6777              }
6778            */
6779      }
6780    else if (e->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
6781      {
6782         bd->client.icccm.fetch.transient_for = 1;
6783         bd->changed = 1;
6784      }
6785    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
6786      {
6787         bd->client.icccm.fetch.client_leader = 1;
6788         bd->changed = 1;
6789      }
6790    else if (e->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
6791      {
6792         bd->client.icccm.fetch.window_role = 1;
6793         bd->changed = 1;
6794      }
6795    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON)
6796      {
6797         bd->client.netwm.fetch.icon = 1;
6798         bd->changed = 1;
6799      }
6800    else if (e->atom == ATM__QTOPIA_SOFT_MENU)
6801      {
6802         bd->client.qtopia.fetch.soft_menu = 1;
6803         bd->changed = 1;
6804      }
6805    else if (e->atom == ATM__QTOPIA_SOFT_MENUS)
6806      {
6807         bd->client.qtopia.fetch.soft_menus = 1;
6808         bd->changed = 1;
6809      }
6810    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
6811      {
6812         bd->client.vkbd.fetch.state = 1;
6813         bd->changed = 1;
6814      }
6815    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
6816      {
6817         bd->client.vkbd.fetch.vkbd = 1;
6818         bd->changed = 1;
6819      }
6820    else if (e->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
6821      {
6822         bd->client.illume.conformant.fetch.conformant = 1;
6823         bd->changed = 1;
6824      }
6825    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
6826      {
6827         bd->client.illume.quickpanel.fetch.state = 1;
6828         bd->changed = 1;
6829      }
6830    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
6831      {
6832         bd->client.illume.quickpanel.fetch.quickpanel = 1;
6833         bd->changed = 1;
6834      }
6835    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
6836      {
6837         bd->client.illume.quickpanel.fetch.priority.major = 1;
6838         bd->changed = 1;
6839      }
6840    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
6841      {
6842         bd->client.illume.quickpanel.fetch.priority.minor = 1;
6843         bd->changed = 1;
6844      }
6845    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
6846      {
6847         bd->client.illume.quickpanel.fetch.zone = 1;
6848         bd->changed = 1;
6849      }
6850    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
6851      {
6852         bd->client.illume.drag.fetch.locked = 1;
6853         bd->changed = 1;
6854      }
6855    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
6856      {
6857         bd->client.illume.drag.fetch.drag = 1;
6858         bd->changed = 1;
6859      }
6860    else if (e->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
6861      {
6862         bd->client.illume.win_state.fetch.state = 1;
6863         bd->changed = 1;
6864      }
6865    /*
6866       else if (e->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
6867       {
6868         bd->client.netwm.fetch.user_time = 1;
6869         bd->changed = 1;
6870       }
6871       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT)
6872       {
6873         bd->client.netwm.fetch.strut = 1;
6874         bd->changed = 1;
6875       }
6876       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
6877       {
6878         bd->client.netwm.fetch.strut = 1;
6879         bd->changed = 1;
6880       }
6881     */
6882    else if (e->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
6883      {
6884         //printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
6885      }
6886    else if (e->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
6887      {
6888         bd->client.e.fetch.video_position = 1;
6889         bd->changed = 1;
6890      }
6891    else if (e->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
6892      {
6893         bd->client.e.fetch.video_parent = 1;
6894         bd->changed = 1;
6895      }
6896    else if (e->atom == ECORE_X_ATOM_NET_WM_STATE)
6897      {
6898         bd->client.netwm.fetch.state = 1;
6899         bd->changed = 1;
6900      }
6901 #ifdef _F_USE_DESK_WINDOW_PROFILE_
6902    else if (e->atom == ECORE_X_ATOM_E_PROFILE_LIST)
6903      {
6904         bd->client.e.fetch.profile_list = 1;
6905         bd->changed = 1;
6906      }
6907 #endif
6908 #ifdef _F_ZONE_WINDOW_ROTATION_
6909    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED)
6910      {
6911         if (e_config->wm_win_rotation)
6912           {
6913              bd->client.e.fetch.rot.support = 1;
6914              bd->changed = 1;
6915           }
6916      }
6917    else if ((e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) ||
6918             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) ||
6919             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) ||
6920             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY))
6921      {
6922         if (e_config->wm_win_rotation)
6923           {
6924              bd->client.e.fetch.rot.geom_hint = 1;
6925              bd->changed = 1;
6926           }
6927      }
6928    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED)
6929      {
6930         if (e_config->wm_win_rotation)
6931           {
6932              bd->client.e.fetch.rot.app_set = 1;
6933              bd->changed = 1;
6934           }
6935      }
6936    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION)
6937      {
6938         if (e_config->wm_win_rotation)
6939           {
6940              bd->client.e.fetch.rot.preferred_rot = 1;
6941              bd->changed = 1;
6942           }
6943      }
6944    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)
6945      {
6946         if (e_config->wm_win_rotation)
6947           {
6948              bd->client.e.fetch.rot.available_rots = 1;
6949              bd->changed = 1;
6950           }
6951      }
6952 #endif
6953
6954    return ECORE_CALLBACK_PASS_ON;
6955 }
6956
6957 static Eina_Bool
6958 _e_border_cb_window_colormap(void *data  __UNUSED__,
6959                              int ev_type __UNUSED__,
6960                              void       *ev)
6961 {
6962    E_Border *bd;
6963    Ecore_X_Event_Window_Colormap *e;
6964
6965    e = ev;
6966    bd = e_border_find_by_client_window(e->win);
6967    if (!bd) return ECORE_CALLBACK_PASS_ON;
6968    return ECORE_CALLBACK_PASS_ON;
6969 }
6970
6971 static Eina_Bool
6972 _e_border_cb_window_shape(void *data  __UNUSED__,
6973                           int ev_type __UNUSED__,
6974                           void       *ev)
6975 {
6976    E_Border *bd;
6977    Ecore_X_Event_Window_Shape *e;
6978
6979    e = ev;
6980    bd = e_border_find_by_client_window(e->win);
6981
6982    if (e->type == ECORE_X_SHAPE_INPUT)
6983      {
6984         if (bd)
6985           {
6986              bd->need_shape_merge = 1;
6987 // YYY             bd->shaped_input = 1;
6988              bd->changes.shape_input = 1;
6989              bd->changed = 1;
6990           }
6991
6992         return ECORE_CALLBACK_PASS_ON;
6993      }
6994
6995    if (bd)
6996      {
6997         bd->changes.shape = 1;
6998         bd->changed = 1;
6999         return ECORE_CALLBACK_PASS_ON;
7000      }
7001    bd = e_border_find_by_window(e->win);
7002    if (bd)
7003      {
7004         bd->need_shape_export = 1;
7005         bd->changed = 1;
7006         return ECORE_CALLBACK_PASS_ON;
7007      }
7008    bd = e_border_find_by_frame_window(e->win);
7009    if (bd)
7010      {
7011         bd->need_shape_merge = 1;
7012         bd->changed = 1;
7013         return ECORE_CALLBACK_PASS_ON;
7014      }
7015    return ECORE_CALLBACK_PASS_ON;
7016 }
7017
7018 static Eina_Bool
7019 _e_border_cb_window_focus_in(void *data  __UNUSED__,
7020                              int ev_type __UNUSED__,
7021                              void       *ev)
7022 {
7023    E_Border *bd;
7024    Ecore_X_Event_Window_Focus_In *e;
7025
7026    e = ev;
7027    bd = e_border_find_by_client_window(e->win);
7028    if (!bd) return ECORE_CALLBACK_PASS_ON;
7029 #ifdef INOUTDEBUG_FOCUS
7030    {
7031       time_t t;
7032       char *ct;
7033
7034       const char *modes[] = {
7035         "MODE_NORMAL",
7036         "MODE_WHILE_GRABBED",
7037         "MODE_GRAB",
7038         "MODE_UNGRAB"
7039       };
7040       const char *details[] = {
7041         "DETAIL_ANCESTOR",
7042         "DETAIL_VIRTUAL",
7043         "DETAIL_INFERIOR",
7044         "DETAIL_NON_LINEAR",
7045         "DETAIL_NON_LINEAR_VIRTUAL",
7046         "DETAIL_POINTER",
7047         "DETAIL_POINTER_ROOT",
7048         "DETAIL_DETAIL_NONE"
7049       };
7050       t = time(NULL);
7051       ct = ctime(&t);
7052       ct[strlen(ct) - 1] = 0;
7053       DBG("FF ->IN %i 0x%x %s md=%s dt=%s\n",
7054              e->time,
7055              e->win,
7056              ct,
7057              modes[e->mode],
7058              details[e->detail]);
7059
7060       DBG("%s cb focus in %d %d\n",
7061              e_border_name_get(bd),
7062              bd->client.icccm.accepts_focus,
7063              bd->client.icccm.take_focus);
7064    }
7065 #endif
7066    _e_border_pri_raise(bd);
7067    if (e->mode == ECORE_X_EVENT_MODE_GRAB)
7068      {
7069         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
7070      }
7071    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
7072      {
7073         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
7074      }
7075
7076    /* ignore focus in from !take_focus windows, we just gave it em */
7077    /* if (!bd->client.icccm.take_focus)
7078     *   return ECORE_CALLBACK_PASS_ON; */
7079
7080    /* should be equal, maybe some clients dont reply with the proper timestamp ? */
7081    if (e->time >= focus_time)
7082      e_border_focus_set(bd, 1, 0);
7083    return ECORE_CALLBACK_PASS_ON;
7084 }
7085
7086 static Eina_Bool
7087 _e_border_cb_window_focus_out(void *data  __UNUSED__,
7088                               int ev_type __UNUSED__,
7089                               void       *ev)
7090 {
7091    E_Border *bd;
7092    Ecore_X_Event_Window_Focus_Out *e;
7093
7094    e = ev;
7095    bd = e_border_find_by_client_window(e->win);
7096    if (!bd) return ECORE_CALLBACK_PASS_ON;
7097 #ifdef INOUTDEBUG_FOCUS
7098    {
7099       time_t t;
7100       char *ct;
7101
7102       const char *modes[] = {
7103         "MODE_NORMAL",
7104         "MODE_WHILE_GRABBED",
7105         "MODE_GRAB",
7106         "MODE_UNGRAB"
7107       };
7108       const char *details[] = {
7109         "DETAIL_ANCESTOR",
7110         "DETAIL_VIRTUAL",
7111         "DETAIL_INFERIOR",
7112         "DETAIL_NON_LINEAR",
7113         "DETAIL_NON_LINEAR_VIRTUAL",
7114         "DETAIL_POINTER",
7115         "DETAIL_POINTER_ROOT",
7116         "DETAIL_DETAIL_NONE"
7117       };
7118       t = time(NULL);
7119       ct = ctime(&t);
7120       ct[strlen(ct) - 1] = 0;
7121       DBG("FF <-OUT %i 0x%x %s md=%s dt=%s",
7122              e->time,
7123              e->win,
7124              ct,
7125              modes[e->mode],
7126              details[e->detail]);
7127
7128       DBG("%s cb focus out %d %d",
7129              e_border_name_get(bd),
7130              bd->client.icccm.accepts_focus,
7131              bd->client.icccm.take_focus);
7132    }
7133 #endif
7134    _e_border_pri_norm(bd);
7135    if (e->mode == ECORE_X_EVENT_MODE_NORMAL)
7136      {
7137         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
7138         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
7139           return ECORE_CALLBACK_PASS_ON;
7140         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
7141           return ECORE_CALLBACK_PASS_ON;
7142      }
7143    else if (e->mode == ECORE_X_EVENT_MODE_GRAB)
7144      {
7145         if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR) return ECORE_CALLBACK_PASS_ON;
7146         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
7147           return ECORE_CALLBACK_PASS_ON;
7148         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
7149           return ECORE_CALLBACK_PASS_ON;
7150         else if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
7151           return ECORE_CALLBACK_PASS_ON;
7152         else if (e->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
7153           return ECORE_CALLBACK_PASS_ON;
7154      }
7155    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
7156      {
7157         /* for firefox/thunderbird (xul) menu walking */
7158         /* NB: why did i disable this before? */
7159         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
7160         else if (e->detail == ECORE_X_EVENT_DETAIL_POINTER)
7161           return ECORE_CALLBACK_PASS_ON;
7162      }
7163    else if (e->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
7164      {
7165         if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR) return ECORE_CALLBACK_PASS_ON;
7166         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
7167           return ECORE_CALLBACK_PASS_ON;
7168      }
7169    e_border_focus_set(bd, 0, 0);
7170    return ECORE_CALLBACK_PASS_ON;
7171 }
7172
7173 #if _F_BORDER_CLIP_TO_ZONE_
7174 static void
7175 _e_border_shape_input_clip_to_zone(E_Border *bd)
7176 {
7177    /* if (!(e_config->window_out_of_vscreen_limits_partly)) return; */
7178    if (!(bd->visible))
7179      return;
7180
7181    if (!(E_CONTAINS(bd->zone->x, bd->zone->y,
7182                     bd->zone->w, bd->zone->h,
7183                     bd->x, bd->y, bd->w, bd->h)))
7184      {
7185         int x, y, w, h;
7186         x = bd->x; y = bd->y; w = bd->w; h = bd->h;
7187         E_RECTS_CLIP_TO_RECT(x, y, w, h,
7188                              bd->zone->x, bd->zone->y,
7189                              bd->zone->w, bd->zone->h);
7190         x -= bd->x;
7191         y -= bd->y;
7192         ecore_x_window_shape_input_rectangle_set(bd->bg_win, x, y, w, h);
7193         ecore_x_window_shape_input_rectangle_set(bd->win, x, y, w, h);
7194      }
7195    else
7196      {
7197         ecore_x_window_shape_input_rectangle_set(bd->bg_win, 0, 0, bd->w, bd->h);
7198         ecore_x_window_shape_input_rectangle_set(bd->win, 0, 0, bd->w, bd->h);
7199      }
7200 }
7201 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
7202
7203 static Eina_Bool
7204 _e_border_cb_client_message(void *data  __UNUSED__,
7205                             int ev_type __UNUSED__,
7206                             void       *ev)
7207 {
7208    Ecore_X_Event_Client_Message *e;
7209    E_Border *bd;
7210
7211    e = ev;
7212 #ifdef _F_DEICONIFY_APPROVE_
7213    if (e->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
7214      {
7215         if (!e_config->deiconify_approve) return ECORE_CALLBACK_PASS_ON;
7216
7217         bd = e_border_find_by_client_window(e->win);
7218         if (bd)
7219           {
7220              if (bd->client.e.state.deiconify_approve.support)
7221                {
7222                   if (e->data.l[1] != 1) return ECORE_CALLBACK_PASS_ON;
7223                   bd->client.e.state.deiconify_approve.render_done = 1;
7224
7225                   E_Border *ancestor_bd;
7226                   ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
7227                   if (ancestor_bd)
7228                     {
7229                        ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
7230                        bd->client.e.state.deiconify_approve.ancestor = NULL;
7231                     }
7232                   else
7233                     {
7234                        ancestor_bd = bd;
7235                     }
7236
7237                   ELBF(ELBT_BD, 0, bd->client.win,
7238                        "RECEIVE DEICONIFY_APPROVE.. ancestor:%x", ancestor_bd->client.win);
7239
7240                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
7241                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
7242                     {
7243                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
7244                          {
7245                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
7246                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
7247
7248                             if (bd->client.e.state.deiconify_approve.wait_timer)
7249                               {
7250                                  ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer);
7251                                  bd->client.e.state.deiconify_approve.wait_timer = NULL;
7252                               }
7253
7254                             e_border_uniconify(ancestor_bd);
7255                          }
7256                        else
7257                          {
7258                             ELB(ELBT_BD, "Unset DEICONIFY_APPROVE render_done", ancestor_bd->client.win);
7259                             ancestor_bd->client.e.state.deiconify_approve.render_done = 0;
7260                          }
7261                     }
7262
7263                   if (bd != ancestor_bd)
7264                     {
7265                        if (bd->client.e.state.deiconify_approve.wait_timer)
7266                          {
7267                             ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer);
7268                             bd->client.e.state.deiconify_approve.wait_timer = NULL;
7269                          }
7270                     }
7271                }
7272           }
7273         return ECORE_CALLBACK_PASS_ON;
7274      }
7275 #endif
7276
7277 #ifdef _F_ZONE_WINDOW_ROTATION_
7278    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
7279
7280    bd = e_border_find_by_client_window(e->win);
7281    if (!bd)
7282      {
7283         if (e_config->wm_win_rotation)
7284           {
7285              Ecore_X_Event_Client_Message *msg = NULL;
7286              Ecore_X_Atom t = e->message_type;
7287              if ((t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)  ||
7288                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE) ||
7289                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)   ||
7290                  (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE))
7291                {
7292                   msg = E_NEW(Ecore_X_Event_Client_Message, 1);
7293                   if (!msg) return ECORE_CALLBACK_PASS_ON;
7294
7295                   msg->win = e->win;
7296                   msg->message_type = e->message_type;
7297                   msg->data.l[0] = e->data.l[0];
7298                   msg->data.l[1] = e->data.l[1];
7299                   msg->data.l[2] = e->data.l[2];
7300                   msg->data.l[3] = e->data.l[3];
7301                   msg->data.l[4] = e->data.l[4];
7302                   rot.msgs = eina_list_append(rot.msgs, msg);
7303
7304                   rot.fetch = EINA_TRUE;
7305                }
7306           }
7307         return ECORE_CALLBACK_PASS_ON;
7308      }
7309
7310    if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE)
7311      {
7312         ELBF(ELBT_ROT, 0, e->data.l[0], "GET ROT_DONE a%d %dx%d zone_a:%d",
7313              e->data.l[1], e->data.l[2], e->data.l[3], bd->zone->rot.curr);
7314
7315         if (e_config->wm_win_rotation)
7316           {
7317              if ((int)e->data.l[1] == bd->client.e.state.rot.curr)
7318                {
7319                   _e_border_rotation_list_remove(bd);
7320                   if (bd->client.e.state.rot.pending_show)
7321                     {
7322                        ELB(ELBT_BD, "SHOW_BD (PEND)", bd->client.win);
7323                        e_border_show(bd);
7324 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
7325                        if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
7326                          _e_border_check_stack(bd);
7327 #endif
7328                        bd->client.e.state.rot.pending_show = 0;
7329                     }
7330                }
7331           }
7332      }
7333 #endif
7334    return ECORE_CALLBACK_PASS_ON;
7335 }
7336
7337 static Eina_Bool
7338 _e_border_cb_window_state_request(void *data  __UNUSED__,
7339                                   int ev_type __UNUSED__,
7340                                   void       *ev)
7341 {
7342    E_Border *bd;
7343    Ecore_X_Event_Window_State_Request *e;
7344    int i;
7345
7346    e = ev;
7347    bd = e_border_find_by_client_window(e->win);
7348    if (!bd) return ECORE_CALLBACK_PASS_ON;
7349
7350    for (i = 0; i < 2; i++)
7351      e_hints_window_state_update(bd, e->state[i], e->action);
7352
7353    return ECORE_CALLBACK_PASS_ON;
7354 }
7355
7356 static Eina_Bool
7357 _e_border_cb_window_move_resize_request(void *data  __UNUSED__,
7358                                         int ev_type __UNUSED__,
7359                                         void       *ev)
7360 {
7361    E_Border *bd;
7362    Ecore_X_Event_Window_Move_Resize_Request *e;
7363
7364    e = ev;
7365    bd = e_border_find_by_client_window(e->win);
7366    if (!bd) return ECORE_CALLBACK_PASS_ON;
7367
7368    if ((bd->shaded) || (bd->shading) ||
7369        (bd->fullscreen) || (bd->moving) ||
7370        (bd->resize_mode != RESIZE_NONE))
7371      return ECORE_CALLBACK_PASS_ON;
7372
7373    if ((e->button >= 1) && (e->button <= 3))
7374      {
7375         bd->mouse.last_down[e->button - 1].mx = e->x;
7376         bd->mouse.last_down[e->button - 1].my = e->y;
7377         bd->mouse.last_down[e->button - 1].x = bd->x;
7378         bd->mouse.last_down[e->button - 1].y = bd->y;
7379         bd->mouse.last_down[e->button - 1].w = bd->w;
7380         bd->mouse.last_down[e->button - 1].h = bd->h;
7381      }
7382    else
7383      {
7384         bd->moveinfo.down.x = bd->x;
7385         bd->moveinfo.down.y = bd->y;
7386         bd->moveinfo.down.w = bd->w;
7387         bd->moveinfo.down.h = bd->h;
7388      }
7389    bd->mouse.current.mx = e->x;
7390    bd->mouse.current.my = e->y;
7391    bd->moveinfo.down.button = e->button;
7392    bd->moveinfo.down.mx = e->x;
7393    bd->moveinfo.down.my = e->y;
7394    grabbed = 1;
7395
7396    if (!bd->lock_user_stacking)
7397      e_border_raise(bd);
7398
7399    if (e->direction == MOVE)
7400      {
7401         bd->cur_mouse_action = e_action_find("window_move");
7402         if (bd->cur_mouse_action)
7403           {
7404              if ((!bd->cur_mouse_action->func.end_mouse) &&
7405                  (!bd->cur_mouse_action->func.end))
7406                bd->cur_mouse_action = NULL;
7407              if (bd->cur_mouse_action)
7408                {
7409                   e_object_ref(E_OBJECT(bd->cur_mouse_action));
7410                   bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
7411                }
7412           }
7413         return ECORE_CALLBACK_PASS_ON;
7414      }
7415
7416    if (!_e_border_resize_begin(bd))
7417      return ECORE_CALLBACK_PASS_ON;
7418
7419    switch (e->direction)
7420      {
7421       case RESIZE_TL:
7422         bd->resize_mode = RESIZE_TL;
7423         GRAV_SET(bd, ECORE_X_GRAVITY_SE);
7424         break;
7425
7426       case RESIZE_T:
7427         bd->resize_mode = RESIZE_T;
7428         GRAV_SET(bd, ECORE_X_GRAVITY_S);
7429         break;
7430
7431       case RESIZE_TR:
7432         bd->resize_mode = RESIZE_TR;
7433         GRAV_SET(bd, ECORE_X_GRAVITY_SW);
7434         break;
7435
7436       case RESIZE_R:
7437         bd->resize_mode = RESIZE_R;
7438         GRAV_SET(bd, ECORE_X_GRAVITY_W);
7439         break;
7440
7441       case RESIZE_BR:
7442         bd->resize_mode = RESIZE_BR;
7443         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
7444         break;
7445
7446       case RESIZE_B:
7447         bd->resize_mode = RESIZE_B;
7448         GRAV_SET(bd, ECORE_X_GRAVITY_N);
7449         break;
7450
7451       case RESIZE_BL:
7452         bd->resize_mode = RESIZE_BL;
7453         GRAV_SET(bd, ECORE_X_GRAVITY_NE);
7454         break;
7455
7456       case RESIZE_L:
7457         bd->resize_mode = RESIZE_L;
7458         GRAV_SET(bd, ECORE_X_GRAVITY_E);
7459         break;
7460
7461       default:
7462         return ECORE_CALLBACK_PASS_ON;
7463      }
7464
7465    bd->cur_mouse_action = e_action_find("window_resize");
7466    if (bd->cur_mouse_action)
7467      {
7468         if ((!bd->cur_mouse_action->func.end_mouse) &&
7469             (!bd->cur_mouse_action->func.end))
7470           bd->cur_mouse_action = NULL;
7471      }
7472    if (bd->cur_mouse_action)
7473      e_object_ref(E_OBJECT(bd->cur_mouse_action));
7474
7475    return ECORE_CALLBACK_PASS_ON;
7476 }
7477
7478 static Eina_Bool
7479 _e_border_cb_desktop_change(void *data  __UNUSED__,
7480                             int ev_type __UNUSED__,
7481                             void       *ev)
7482 {
7483    E_Border *bd;
7484    Ecore_X_Event_Desktop_Change *e;
7485
7486    e = ev;
7487    bd = e_border_find_by_client_window(e->win);
7488    if (bd)
7489      {
7490         if (e->desk == 0xffffffff)
7491           e_border_stick(bd);
7492         else if ((int)e->desk < (bd->zone->desk_x_count * bd->zone->desk_y_count))
7493           {
7494              E_Desk *desk;
7495
7496              desk = e_desk_at_pos_get(bd->zone, e->desk);
7497              if (desk)
7498                e_border_desk_set(bd, desk);
7499           }
7500      }
7501    else
7502      {
7503         ecore_x_netwm_desktop_set(e->win, e->desk);
7504      }
7505    return ECORE_CALLBACK_PASS_ON;
7506 }
7507
7508 static Eina_Bool
7509 _e_border_cb_sync_alarm(void *data  __UNUSED__,
7510                         int ev_type __UNUSED__,
7511                         void       *ev)
7512 {
7513    E_Border *bd;
7514    Ecore_X_Event_Sync_Alarm *e;
7515    unsigned int serial;
7516
7517    e = ev;
7518    bd = e_border_find_by_alarm(e->alarm);
7519    if (!bd) return ECORE_CALLBACK_PASS_ON;
7520
7521    if (bd->client.netwm.sync.wait)
7522      bd->client.netwm.sync.wait--;
7523
7524    if (ecore_x_sync_counter_query(bd->client.netwm.sync.counter, &serial))
7525      {
7526         E_Border_Pending_Move_Resize *pnd = NULL;
7527
7528         /* skip pending for which we didn't get a reply */
7529         while (bd->pending_move_resize)
7530           {
7531              pnd = bd->pending_move_resize->data;
7532              bd->pending_move_resize = eina_list_remove(bd->pending_move_resize, pnd);
7533
7534              if (serial == pnd->serial)
7535                break;
7536
7537              E_FREE(pnd);
7538           }
7539
7540         if (pnd)
7541           {
7542              bd->x = pnd->x;
7543              bd->y = pnd->y;
7544              bd->w = pnd->w;
7545              bd->h = pnd->h;
7546              bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
7547              bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
7548              E_FREE(pnd);
7549           }
7550      }
7551
7552    bd->changes.size = 1;
7553    bd->changes.pos = 1;
7554
7555    _e_border_eval(bd);
7556    evas_render(bd->bg_evas);
7557
7558    ecore_x_pointer_xy_get(e_manager_current_get()->root,
7559                           &bd->mouse.current.mx,
7560                           &bd->mouse.current.my);
7561
7562    bd->client.netwm.sync.send_time = ecore_loop_time_get();
7563    _e_border_resize_handle(bd);
7564
7565    return ECORE_CALLBACK_PASS_ON;
7566 }
7567
7568 static Eina_Bool
7569 _e_border_cb_efreet_cache_update(void *data  __UNUSED__,
7570                                  int ev_type __UNUSED__,
7571                                  void *ev    __UNUSED__)
7572 {
7573    Eina_List *l;
7574    E_Border *bd;
7575
7576    /* mark all borders for desktop/icon updates */
7577    EINA_LIST_FOREACH(borders, l, bd)
7578      {
7579         if (bd->desktop)
7580           {
7581              efreet_desktop_free(bd->desktop);
7582              bd->desktop = NULL;
7583           }
7584         bd->changes.icon = 1;
7585         bd->changed = 1;
7586      }
7587    /*
7588       e_init_status_set(_("Desktop files scan done"));
7589       e_init_done();
7590     */
7591    return ECORE_CALLBACK_PASS_ON;
7592 }
7593
7594 static Eina_Bool
7595 _e_border_cb_config_icon_theme(void *data  __UNUSED__,
7596                                int ev_type __UNUSED__,
7597                                void *ev    __UNUSED__)
7598 {
7599    Eina_List *l;
7600    E_Border *bd;
7601
7602    /* mark all borders for desktop/icon updates */
7603    EINA_LIST_FOREACH(borders, l, bd)
7604      {
7605         bd->changes.icon = 1;
7606         bd->changed = 1;
7607      }
7608    return ECORE_CALLBACK_PASS_ON;
7609 }
7610
7611 static Eina_Bool
7612 _e_border_cb_pointer_warp(void *data  __UNUSED__,
7613                           int ev_type __UNUSED__,
7614                           void       *ev)
7615 {
7616    E_Event_Pointer_Warp *e;
7617
7618    e = ev;
7619    if (!bdmove) return ECORE_CALLBACK_PASS_ON;
7620    e_border_move(bdmove, bdmove->x + (e->curr.x - e->prev.x), bdmove->y + (e->curr.y - e->prev.y));
7621    return ECORE_CALLBACK_PASS_ON;
7622 }
7623
7624 static void
7625 _e_border_cb_signal_bind(void            *data,
7626                          Evas_Object *obj __UNUSED__,
7627                          const char      *emission,
7628                          const char      *source)
7629 {
7630    E_Border *bd;
7631
7632    bd = data;
7633    if (e_dnd_active()) return;
7634    e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd),
7635                             emission, source);
7636 }
7637
7638 static Eina_Bool
7639 _e_border_cb_mouse_in(void    *data,
7640                       int type __UNUSED__,
7641                       void    *event)
7642 {
7643    Ecore_X_Event_Mouse_In *ev;
7644    E_Border *bd;
7645
7646    ev = event;
7647    bd = data;
7648 #ifdef INOUTDEBUG_MOUSE
7649    {
7650       time_t t;
7651       char *ct;
7652
7653       const char *modes[] = {
7654          "MODE_NORMAL",
7655          "MODE_WHILE_GRABBED",
7656          "MODE_GRAB",
7657          "MODE_UNGRAB"
7658       };
7659       const char *details[] = {
7660          "DETAIL_ANCESTOR",
7661          "DETAIL_VIRTUAL",
7662          "DETAIL_INFERIOR",
7663          "DETAIL_NON_LINEAR",
7664          "DETAIL_NON_LINEAR_VIRTUAL",
7665          "DETAIL_POINTER",
7666          "DETAIL_POINTER_ROOT",
7667          "DETAIL_DETAIL_NONE"
7668       };
7669       t = time(NULL);
7670       ct = ctime(&t);
7671       ct[strlen(ct) - 1] = 0;
7672       DBG("@@ ->IN 0x%x 0x%x %s md=%s dt=%s",
7673              ev->win, ev->event_win,
7674              ct,
7675              modes[ev->mode],
7676              details[ev->detail]);
7677    }
7678 #endif
7679    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7680    if (ev->event_win == bd->win)
7681      {
7682         e_focus_event_mouse_in(bd);
7683      }
7684 #if 0
7685    if ((ev->win != bd->win) &&
7686        (ev->win != bd->event_win) &&
7687        (ev->event_win != bd->win) &&
7688        (ev->event_win != bd->event_win))
7689      return ECORE_CALLBACK_PASS_ON;
7690 #else
7691    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7692 #endif
7693    bd->mouse.current.mx = ev->root.x;
7694    bd->mouse.current.my = ev->root.y;
7695    if (!bd->bg_evas_in)
7696      {
7697         evas_event_feed_mouse_in(bd->bg_evas, ev->time, NULL);
7698         bd->bg_evas_in = EINA_TRUE;
7699      }
7700    return ECORE_CALLBACK_PASS_ON;
7701 }
7702
7703 static Eina_Bool
7704 _e_border_cb_mouse_out(void    *data,
7705                        int type __UNUSED__,
7706                        void    *event)
7707 {
7708    Ecore_X_Event_Mouse_Out *ev;
7709    E_Border *bd;
7710
7711    ev = event;
7712    bd = data;
7713 #ifdef INOUTDEBUG_MOUSE
7714    {
7715       time_t t;
7716       char *ct;
7717
7718       const char *modes[] = {
7719          "MODE_NORMAL",
7720          "MODE_WHILE_GRABBED",
7721          "MODE_GRAB",
7722          "MODE_UNGRAB"
7723       };
7724       const char *details[] = {
7725          "DETAIL_ANCESTOR",
7726          "DETAIL_VIRTUAL",
7727          "DETAIL_INFERIOR",
7728          "DETAIL_NON_LINEAR",
7729          "DETAIL_NON_LINEAR_VIRTUAL",
7730          "DETAIL_POINTER",
7731          "DETAIL_POINTER_ROOT",
7732          "DETAIL_DETAIL_NONE"
7733       };
7734       t = time(NULL);
7735       ct = ctime(&t);
7736       ct[strlen(ct) - 1] = 0;
7737       DBG("@@ <-OUT 0x%x 0x%x %s md=%s dt=%s",
7738              ev->win, ev->event_win,
7739              ct,
7740              modes[ev->mode],
7741              details[ev->detail]);
7742    }
7743 #endif
7744    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7745    if (ev->event_win == bd->win)
7746      {
7747         if (bd->fullscreen)
7748           return ECORE_CALLBACK_PASS_ON;
7749         if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
7750             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7751           return ECORE_CALLBACK_PASS_ON;
7752         if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7753           return ECORE_CALLBACK_PASS_ON;
7754         if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
7755             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7756           return ECORE_CALLBACK_PASS_ON;
7757         e_focus_event_mouse_out(bd);
7758      }
7759 #if 0
7760    if ((ev->win != bd->win) &&
7761        (ev->win != bd->event_win) &&
7762        (ev->event_win != bd->win) &&
7763        (ev->event_win != bd->event_win))
7764      return ECORE_CALLBACK_PASS_ON;
7765 #else
7766    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7767 #endif
7768    bd->mouse.current.mx = ev->root.x;
7769    bd->mouse.current.my = ev->root.y;
7770    if (bd->bg_evas_in)
7771      {
7772         if (!((evas_event_down_count_get(bd->bg_evas) > 0) &&
7773               (!((ev->mode == ECORE_X_EVENT_MODE_GRAB) &&
7774                  (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)))))
7775           {
7776              if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7777                evas_event_feed_mouse_cancel(bd->bg_evas, ev->time, NULL);
7778              evas_event_feed_mouse_out(bd->bg_evas, ev->time, NULL);
7779              bd->bg_evas_in = EINA_FALSE;
7780           }
7781      }
7782    return ECORE_CALLBACK_PASS_ON;
7783 }
7784
7785 static Eina_Bool
7786 _e_border_cb_mouse_wheel(void    *data,
7787                          int type __UNUSED__,
7788                          void    *event)
7789 {
7790    Ecore_Event_Mouse_Wheel *ev;
7791    E_Border *bd;
7792
7793    ev = event;
7794    bd = data;
7795    if ((ev->event_window == bd->win) ||
7796        (ev->event_window == bd->event_win))
7797      {
7798         bd->mouse.current.mx = ev->root.x;
7799         bd->mouse.current.my = ev->root.y;
7800         if (!bd->cur_mouse_action)
7801           e_bindings_wheel_event_handle(E_BINDING_CONTEXT_WINDOW,
7802                                         E_OBJECT(bd), ev);
7803      }
7804    evas_event_feed_mouse_wheel(bd->bg_evas, ev->direction, ev->z, ev->timestamp, NULL);
7805    return ECORE_CALLBACK_PASS_ON;
7806 }
7807
7808 static Eina_Bool
7809 _e_border_cb_mouse_down(void    *data,
7810                         int type __UNUSED__,
7811                         void    *event)
7812 {
7813    Ecore_Event_Mouse_Button *ev;
7814    E_Border *bd;
7815
7816    ev = event;
7817    bd = data;
7818    if ((ev->event_window == bd->win) ||
7819        (ev->event_window == bd->event_win))
7820      {
7821         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7822           {
7823              bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7824              bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7825              bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7826              bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7827              bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7828              bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7829           }
7830         else
7831           {
7832              bd->moveinfo.down.x = bd->x + bd->fx.x;
7833              bd->moveinfo.down.y = bd->y + bd->fx.y;
7834              bd->moveinfo.down.w = bd->w;
7835              bd->moveinfo.down.h = bd->h;
7836           }
7837         bd->mouse.current.mx = ev->root.x;
7838         bd->mouse.current.my = ev->root.y;
7839         if (!bd->cur_mouse_action)
7840           {
7841              bd->cur_mouse_action =
7842                e_bindings_mouse_down_event_handle(E_BINDING_CONTEXT_WINDOW,
7843                                                   E_OBJECT(bd), ev);
7844              if (bd->cur_mouse_action)
7845                {
7846                   if ((!bd->cur_mouse_action->func.end_mouse) &&
7847                       (!bd->cur_mouse_action->func.end))
7848                     bd->cur_mouse_action = NULL;
7849                   if (bd->cur_mouse_action)
7850                     e_object_ref(E_OBJECT(bd->cur_mouse_action));
7851                }
7852           }
7853         e_focus_event_mouse_down(bd);
7854      }
7855    if (ev->window != ev->event_window)
7856      {
7857         return 1;
7858      }
7859    if ((ev->window != bd->event_win) && (ev->event_window != bd->win))
7860      {
7861         return 1;
7862      }
7863    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7864      {
7865         bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7866         bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7867         bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7868         bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7869         bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7870         bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7871      }
7872    else
7873      {
7874         bd->moveinfo.down.x = bd->x + bd->fx.x;
7875         bd->moveinfo.down.y = bd->y + bd->fx.y;
7876         bd->moveinfo.down.w = bd->w;
7877         bd->moveinfo.down.h = bd->h;
7878      }
7879    bd->mouse.current.mx = ev->root.x;
7880    bd->mouse.current.my = ev->root.y;
7881 /*
7882    if (bd->moving)
7883      {
7884      }
7885    else if (bd->resize_mode != RESIZE_NONE)
7886      {
7887      }
7888    else
7889  */
7890    {
7891       Evas_Button_Flags flags = EVAS_BUTTON_NONE;
7892
7893       if (ev->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
7894       if (ev->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
7895       evas_event_feed_mouse_down(bd->bg_evas, ev->buttons, flags, ev->timestamp, NULL);
7896    }
7897    return ECORE_CALLBACK_PASS_ON;
7898 }
7899
7900 static Eina_Bool
7901 _e_border_cb_mouse_up(void    *data,
7902                       int type __UNUSED__,
7903                       void    *event)
7904 {
7905    Ecore_Event_Mouse_Button *ev;
7906    E_Border *bd;
7907
7908    ev = event;
7909    bd = data;
7910    if ((ev->event_window == bd->win) ||
7911        (ev->event_window == bd->event_win))
7912      {
7913         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7914           {
7915              bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7916              bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7917              bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7918              bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7919           }
7920         bd->mouse.current.mx = ev->root.x;
7921         bd->mouse.current.my = ev->root.y;
7922         /* also we dont pass the same params that went in - then again that */
7923         /* should be ok as we are just ending the action if it has an end */
7924         if (bd->cur_mouse_action)
7925           {
7926              if (bd->cur_mouse_action->func.end_mouse)
7927                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", ev);
7928              else if (bd->cur_mouse_action->func.end)
7929                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
7930              e_object_unref(E_OBJECT(bd->cur_mouse_action));
7931              bd->cur_mouse_action = NULL;
7932           }
7933         else
7934           {
7935              if (!e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd), ev))
7936                e_focus_event_mouse_up(bd);
7937           }
7938      }
7939    if (ev->window != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7940    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7941      {
7942         bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7943         bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7944         bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7945         bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7946      }
7947    bd->mouse.current.mx = ev->root.x;
7948    bd->mouse.current.my = ev->root.y;
7949
7950    bd->drag.start = 0;
7951
7952    evas_event_feed_mouse_up(bd->bg_evas, ev->buttons, EVAS_BUTTON_NONE, ev->timestamp, NULL);
7953    return ECORE_CALLBACK_PASS_ON;
7954 }
7955
7956 static void
7957 _e_border_stay_within_container(E_Border *bd, int x, int y, int *new_x, int *new_y)
7958 {
7959 #ifdef _F_BORDER_CLIP_TO_ZONE_
7960    int new_x_max, new_y_max;
7961    int new_x_min, new_y_min;
7962    int margin_x, margin_y;
7963
7964    margin_x = bd->w - 100;
7965    margin_y = bd->h - 100;
7966
7967    new_x_max = bd->zone->x + bd->zone->w - bd->w + margin_x;
7968    new_x_min = bd->zone->x - margin_x;
7969    new_y_max = bd->zone->y + bd->zone->h - bd->h + margin_y;
7970    new_y_min = bd->zone->y - margin_y;
7971
7972    if (x >= new_x_max)      *new_x = new_x_max;
7973    else if (x <= new_x_min) *new_x = new_x_min;
7974
7975    if (y >= new_y_max)      *new_y = new_y_max;
7976    else if (y <= new_y_min) *new_y = new_y_min;
7977 #endif
7978 }
7979
7980 static Eina_Bool
7981 _e_border_cb_mouse_move(void    *data,
7982                         int type __UNUSED__,
7983                         void    *event)
7984 {
7985    Ecore_Event_Mouse_Move *ev;
7986    E_Border *bd;
7987
7988    ev = event;
7989    bd = data;
7990    if ((ev->window != bd->event_win) &&
7991        (ev->event_window != bd->win)) return ECORE_CALLBACK_PASS_ON;
7992    bd->mouse.current.mx = ev->root.x;
7993    bd->mouse.current.my = ev->root.y;
7994    if (bd->moving)
7995      {
7996         int x, y, new_x, new_y;
7997         int new_w, new_h;
7998         Eina_List *skiplist = NULL;
7999 #if 0
8000         // FIXME: remove? sync what for when only moving?
8001         if ((ecore_loop_time_get() - bd->client.netwm.sync.time) > 0.5)
8002           bd->client.netwm.sync.wait = 0;
8003         if ((bd->client.netwm.sync.request) &&
8004             (bd->client.netwm.sync.alarm) &&
8005             (bd->client.netwm.sync.wait > 1)) return ECORE_CALLBACK_PASS_ON;
8006 #endif
8007         if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
8008           {
8009              x = bd->mouse.last_down[bd->moveinfo.down.button - 1].x +
8010                (bd->mouse.current.mx - bd->moveinfo.down.mx);
8011              y = bd->mouse.last_down[bd->moveinfo.down.button - 1].y +
8012                (bd->mouse.current.my - bd->moveinfo.down.my);
8013           }
8014         else
8015           {
8016              x = bd->moveinfo.down.x +
8017                (bd->mouse.current.mx - bd->moveinfo.down.mx);
8018              y = bd->moveinfo.down.y +
8019                (bd->mouse.current.my - bd->moveinfo.down.my);
8020           }
8021         new_x = x;
8022         new_y = y;
8023
8024 #ifdef _F_USE_RESIST_MAGNETIC_EFFECT_
8025         skiplist = eina_list_append(skiplist, bd);
8026         e_resist_container_border_position(bd->zone->container, skiplist,
8027                                            bd->x, bd->y, bd->w, bd->h,
8028                                            x, y, bd->w, bd->h,
8029                                            &new_x, &new_y, &new_w, &new_h);
8030         eina_list_free(skiplist);
8031
8032         _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
8033 #else
8034         /* if (e_config->window_out_of_vscreen_limits_partly) */
8035         if (1)
8036           _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
8037         else
8038           {
8039              skiplist = eina_list_append(skiplist, bd);
8040              e_resist_container_border_position(bd->zone->container, skiplist,
8041                                                 bd->x, bd->y, bd->w, bd->h,
8042                                                 x, y, bd->w, bd->h,
8043                                                 &new_x, &new_y, &new_w, &new_h);
8044              eina_list_free(skiplist);
8045           }
8046 #endif
8047         bd->shelf_fix.x = 0;
8048         bd->shelf_fix.y = 0;
8049         bd->shelf_fix.modified = 0;
8050         e_border_move(bd, new_x, new_y);
8051         e_zone_flip_coords_handle(bd->zone, ev->root.x, ev->root.y);
8052      }
8053    else if (bd->resize_mode != RESIZE_NONE)
8054      {
8055         if ((bd->client.netwm.sync.request) &&
8056             (bd->client.netwm.sync.alarm))
8057           {
8058              if ((ecore_loop_time_get() - bd->client.netwm.sync.send_time) > 0.5)
8059                {
8060                   E_Border_Pending_Move_Resize *pnd;
8061
8062                   if (bd->pending_move_resize)
8063                     {
8064                        bd->changes.pos = 1;
8065                        bd->changes.size = 1;
8066                        bd->changed = 1;
8067                        _e_border_client_move_resize_send(bd);
8068                     }
8069                   EINA_LIST_FREE(bd->pending_move_resize, pnd)
8070                     E_FREE(pnd);
8071
8072                   bd->client.netwm.sync.wait = 0;
8073                }
8074              /* sync.wait is incremented when resize_handle sends
8075               * sync-request and decremented by sync-alarm cb. so
8076               * we resize here either on initial resize, timeout or
8077               * when no new resize-request was added by sync-alarm cb.
8078               */
8079              if (!bd->client.netwm.sync.wait)
8080                _e_border_resize_handle(bd);
8081           }
8082         else
8083           _e_border_resize_handle(bd);
8084      }
8085    else
8086      {
8087         if (bd->drag.start)
8088           {
8089              if ((bd->drag.x == -1) && (bd->drag.y == -1))
8090                {
8091                   bd->drag.x = ev->root.x;
8092                   bd->drag.y = ev->root.y;
8093                }
8094              else
8095                {
8096                   int dx, dy;
8097
8098                   dx = bd->drag.x - ev->root.x;
8099                   dy = bd->drag.y - ev->root.y;
8100                   if (((dx * dx) + (dy * dy)) >
8101                       (e_config->drag_resist * e_config->drag_resist))
8102                     {
8103      /* start drag! */
8104                         if (bd->icon_object)
8105                           {
8106                              Evas_Object *o = NULL;
8107                              Evas_Coord x, y, w, h;
8108                              const char *drag_types[] = { "enlightenment/border" };
8109
8110                              e_object_ref(E_OBJECT(bd));
8111                              evas_object_geometry_get(bd->icon_object,
8112                                                       &x, &y, &w, &h);
8113                              drag_border = e_drag_new(bd->zone->container,
8114                                                       bd->x + bd->fx.x + x,
8115                                                       bd->y + bd->fx.y + y,
8116                                                       drag_types, 1, bd, -1,
8117                                                       NULL,
8118                                                       _e_border_cb_drag_finished);
8119                              o = e_border_icon_add(bd, drag_border->evas);
8120                              if (!o)
8121                                {
8122      /* FIXME: fallback icon for drag */
8123                                    o = evas_object_rectangle_add(drag_border->evas);
8124                                    evas_object_color_set(o, 255, 255, 255, 255);
8125                                }
8126                              e_drag_object_set(drag_border, o);
8127
8128                              e_drag_resize(drag_border, w, h);
8129                              e_drag_start(drag_border, bd->drag.x, bd->drag.y);
8130                           }
8131                         bd->drag.start = 0;
8132                     }
8133                }
8134           }
8135         evas_event_feed_mouse_move(bd->bg_evas, ev->x, ev->y, ev->timestamp, NULL);
8136      }
8137    return ECORE_CALLBACK_PASS_ON;
8138 }
8139
8140 static Eina_Bool
8141 _e_border_cb_grab_replay(void *data __UNUSED__,
8142                          int        type,
8143                          void      *event)
8144 {
8145    Ecore_Event_Mouse_Button *ev;
8146
8147    if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
8148    ev = event;
8149    if ((e_config->pass_click_on)
8150        || (e_config->always_click_to_raise) // this works even if not on click-to-focus
8151        || (e_config->always_click_to_focus) // this works even if not on click-to-focus
8152       )
8153      {
8154         E_Border *bd;
8155
8156         bd = e_border_find_by_window(ev->event_window);
8157         if (bd)
8158           {
8159              if (bd->cur_mouse_action)
8160                return ECORE_CALLBACK_DONE;
8161              if (ev->event_window == bd->win)
8162                {
8163                   if (!e_bindings_mouse_down_find(E_BINDING_CONTEXT_WINDOW,
8164                                                   E_OBJECT(bd), ev, NULL))
8165                     return ECORE_CALLBACK_PASS_ON;
8166                }
8167           }
8168      }
8169    return ECORE_CALLBACK_DONE;
8170 }
8171
8172 static void
8173 _e_border_cb_drag_finished(E_Drag     *drag,
8174                            int dropped __UNUSED__)
8175 {
8176    E_Border *bd;
8177
8178    bd = drag->data;
8179    e_object_unref(E_OBJECT(bd));
8180    drag_border = NULL;
8181 }
8182
8183 #ifdef _F_USE_DESK_WINDOW_PROFILE_
8184 static Eina_Bool
8185 _e_border_cb_desk_window_profile_change(void *data  __UNUSED__,
8186                                         int ev_type __UNUSED__,
8187                                         void       *ev)
8188 {
8189    E_Event_Desk_Window_Profile_Change *e;
8190    Eina_List *l;
8191    E_Border *bd;
8192
8193    e = ev;
8194    EINA_LIST_FOREACH(borders, l, bd)
8195      {
8196         if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
8197           {
8198              bd->client.e.fetch.profile_list = 1;
8199              bd->changed = 1;
8200           }
8201      }
8202    return ECORE_CALLBACK_PASS_ON;
8203 }
8204 #endif
8205
8206 #ifdef _F_ZONE_WINDOW_ROTATION_
8207 static Eina_Bool
8208 _e_border_cb_zone_rotation_change_begin(void *data  __UNUSED__,
8209                                         int ev_type __UNUSED__,
8210                                         void       *ev)
8211 {
8212    E_Event_Zone_Rotation_Change_Begin *e = ev;
8213
8214    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8215    if ((!e) || (!e->zone)) return ECORE_CALLBACK_PASS_ON;
8216
8217    if (!_e_border_rotation_zone_set(e->zone))
8218      {
8219         /* there is no border which supports window manager rotation */
8220         e_zone_rotation_update_cancel(e->zone);
8221      }
8222    return ECORE_CALLBACK_PASS_ON;
8223 }
8224
8225 static void
8226 _e_border_cb_rotation_sync_job(void *data)
8227 {
8228    E_Zone *zone = data;
8229    Eina_List *l;
8230    E_Border_Rotation_Info *info = NULL;
8231
8232    ELBF(ELBT_ROT, 0, zone->id, "DO ROTATION SYNC_JOB rot.list:%p(%d) wait_prepare_done:%d zone_block_count:%d",
8233         rot.list, eina_list_count(rot.list), rot.wait_prepare_done, zone->rot.block_count);
8234    if (rot.list)
8235      {
8236         EINA_LIST_FOREACH(rot.list, l, info)
8237            _e_border_hook_call(E_BORDER_HOOK_ROTATION_LIST_ADD, info->bd);
8238
8239         ELBF(ELBT_ROT, 0, zone->id, "SYNC_JOB list(%d) wait_prepare_done:%d zone_block_count:%d",
8240              eina_list_count(rot.list), rot.wait_prepare_done, zone->rot.block_count);
8241
8242         if (!rot.wait_prepare_done)
8243           {
8244              _e_border_rotation_change_request(zone);
8245           }
8246      }
8247
8248    // clear job
8249    if (rot.sync_job)
8250      {
8251         ELB(ELBT_ROT, "DEL SYNC_JOB", zone->id);
8252         ecore_job_del(rot.sync_job);
8253         rot.sync_job = NULL;
8254      }
8255 }
8256
8257 static void
8258 _e_border_cb_rotation_async_job(void *data)
8259 {
8260    E_Zone *zone = data;
8261
8262    if (rot.list) goto end;
8263
8264    ELB(ELBT_ROT, "FLUSH ASYNC LIST TO ROT_CHANGE_REQ", zone->id);
8265
8266    if (!rot.wait_prepare_done)
8267      {
8268         _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8269         rot.async_list = NULL;
8270      }
8271
8272 end:
8273    // clear async job
8274    if (rot.async_job)
8275      {
8276         ELB(ELBT_ROT, "DEL ASYNC_JOB", zone->id);
8277         ecore_job_del(rot.async_job);
8278         rot.async_job = NULL;
8279      }
8280 }
8281
8282 static Eina_Bool
8283 _e_border_rotation_change_prepare_timeout(void *data)
8284 {
8285    E_Zone *zone = data;
8286    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8287
8288    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE_PREPARE", 0);
8289
8290    if ((zone) && (rot.wait_prepare_done))
8291      {
8292         if (rot.list)
8293           {
8294              _e_border_rotation_change_request(zone);
8295              if (rot.prepare_timer)
8296                ecore_timer_del(rot.prepare_timer);
8297              rot.prepare_timer = NULL;
8298              rot.wait_prepare_done = EINA_FALSE;
8299           }
8300      }
8301    return ECORE_CALLBACK_CANCEL;
8302 }
8303
8304 static void
8305 _e_border_rotation_change_request(E_Zone *zone)
8306 {
8307    if (!e_config->wm_win_rotation) return;
8308    if (!rot.list) return;
8309    if (eina_list_count(rot.list) <= 0) return;
8310    /* pending rotation problem occurred while launching app by the tray */
8311    //if (zone->rot.block_count) return;
8312
8313    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8314    rot.prepare_timer = NULL;
8315    rot.wait_prepare_done = EINA_FALSE;
8316
8317    _e_border_rotation_list_flush(rot.list, EINA_FALSE);
8318
8319    if (rot.done_timer)
8320      ecore_timer_del(rot.done_timer);
8321    ELB(ELBT_ROT, "ADD TIMEOUT ROT_DONE", zone->id);
8322    rot.done_timer = ecore_timer_add(5.0f,
8323                                     _e_border_rotation_change_done_timeout,
8324                                     NULL);
8325 }
8326
8327 static void
8328 _e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush)
8329 {
8330    Eina_List *l;
8331    E_Border_Rotation_Info *info =NULL;
8332    int x, y, w, h;
8333
8334    EINA_LIST_FOREACH (list, l, info)
8335      {
8336         if (!info->bd) continue;
8337         if ((info->bd->client.e.state.rot.wait_for_done) &&
8338             (info->bd->client.e.state.rot.wait_done_ang == info->ang)) continue;
8339
8340         _e_border_event_border_rotation_change_begin_send(info->bd);
8341
8342         /* resize border */
8343         info->win_resize = _e_border_rotation_pre_resize(info->bd, info->ang, &x, &y, &w, &h);
8344         info->bd->client.e.state.rot.pending_change_request = info->win_resize;
8345
8346         info->x = x; info->y = y;
8347         info->w = w; info->h = h;
8348
8349         ELBF(ELBT_ROT, 1, info->bd->client.win,
8350              "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
8351              info->ang, info->win_resize, info->w, info->h);
8352
8353 #ifdef _F_USE_DLOG_
8354              SECURE_SLOGD("[ROTATION] SEND PREP_ROT, win:0x%08x a%d resize%d %dx%d",
8355                           info->bd->client.win, info->ang, info->win_resize,
8356                           info->w, info->h);
8357 #endif
8358
8359         ecore_x_e_window_rotation_change_prepare_send
8360            (info->bd->client.win, info->ang,
8361             info->win_resize, info->w, info->h);
8362
8363         if (!info->bd->client.e.state.rot.pending_change_request)
8364           {
8365              ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
8366 #ifdef _F_USE_DLOG_
8367              SECURE_SLOGD("[ROTATION] SEND REQ_ROT, win:0x%08x, rot:%d",
8368                           info->bd->client.win, info->ang);
8369 #endif
8370              ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
8371                                                            info->ang);
8372              info->bd->client.e.state.rot.wait_for_done = 1;
8373              info->bd->client.e.state.rot.wait_done_ang = info->ang;
8374           }
8375      }
8376
8377    if (flush)
8378      {
8379         EINA_LIST_FREE(list, info)
8380            E_FREE(info);
8381      }
8382 }
8383
8384 EAPI void
8385 e_border_rotation_list_clear(E_Zone *zone, Eina_Bool send_request)
8386 {
8387    E_Border_Rotation_Info *info = NULL;
8388
8389    if (send_request) _e_border_rotation_change_request(zone);
8390    else
8391      {
8392         EINA_LIST_FREE(rot.list, info)
8393            E_FREE(info);
8394         rot.list = NULL;
8395      }
8396 }
8397
8398 static void
8399 _e_border_rotation_list_remove(E_Border *bd)
8400 {
8401    Eina_List *l = NULL;
8402    E_Border_Rotation_Info *info = NULL;
8403    E_Event_Border_Rotation_Change_End *ev = NULL;
8404    Eina_Bool found = EINA_FALSE;
8405
8406    if (!e_config->wm_win_rotation) return;
8407
8408    EINA_LIST_FOREACH(rot.list, l, info)
8409      {
8410         if (info->bd == bd)
8411           {
8412              rot.list = eina_list_remove(rot.list, info);
8413              E_FREE(info);
8414              found = EINA_TRUE;
8415           }
8416      }
8417
8418    if (bd->client.e.state.rot.wait_for_done)
8419      {
8420         bd->client.e.state.rot.wait_for_done = 0;
8421
8422         /* if we make the border event in the _e_border_free function,
8423          * then we may meet a crash problem, only work this at least e_border_hide.
8424          */
8425         if (!e_object_is_del(E_OBJECT(bd)))
8426           {
8427              ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
8428              if (ev)
8429                {
8430                   ev->border = bd;
8431                   e_object_ref(E_OBJECT(bd));
8432                   ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_END,
8433                                   ev,
8434                                   _e_border_event_border_rotation_change_end_free,
8435                                   NULL);
8436                }
8437           }
8438
8439         if ((found) &&
8440             (eina_list_count(rot.list) == 0))
8441           {
8442              _e_border_rotation_change_done();
8443           }
8444      }
8445 }
8446
8447 static Eina_Bool
8448 _e_border_rotation_change_done_timeout(void *data __UNUSED__)
8449 {
8450    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8451    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE", 0);
8452    _e_border_rotation_change_done();
8453    return ECORE_CALLBACK_CANCEL;
8454 }
8455
8456 static void
8457 _e_border_rotation_change_done(void)
8458 {
8459    E_Manager *m = NULL;
8460    E_Border_Rotation_Info *info = NULL;
8461
8462    if (!e_config->wm_win_rotation) return;
8463
8464    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8465    rot.prepare_timer = NULL;
8466
8467    rot.wait_prepare_done = EINA_FALSE;
8468
8469    if (rot.done_timer) ecore_timer_del(rot.done_timer);
8470    rot.done_timer = NULL;
8471
8472    EINA_LIST_FREE(rot.list, info)
8473      {
8474         if (info->bd)
8475           {
8476              ELB(ELBT_ROT, "TIMEOUT ROT_DONE", info->bd->client.win);
8477              if (info->bd->client.e.state.rot.pending_show)
8478                {
8479                   ELB(ELBT_ROT, "SHOW PEND(TIMEOUT)", info->bd->client.win);
8480                   e_border_show(info->bd);
8481 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
8482                   if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
8483                     _e_border_check_stack(info->bd);
8484 #endif
8485                   info->bd->client.e.state.rot.pending_show = 0;
8486                }
8487              info->bd->client.e.state.rot.wait_for_done = 0;
8488           }
8489         E_FREE(info);
8490      }
8491
8492    _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8493
8494    rot.list = NULL;
8495    rot.async_list = NULL;
8496
8497    m = e_manager_current_get();
8498    e_manager_comp_screen_unlock(m);
8499    e_zone_rotation_update_done(e_util_zone_current_get(m));
8500 }
8501
8502 static int
8503 _prev_angle_get(Ecore_X_Window win)
8504 {
8505    int ret, count = 0, ang = -1;
8506    unsigned char* data = NULL;
8507
8508    ret = ecore_x_window_prop_property_get
8509       (win, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
8510       ECORE_X_ATOM_CARDINAL, 32, &data, &count);
8511
8512    if ((ret) && (data) && (count))
8513      ang = ((int *)data)[0];
8514    if (data) free(data);
8515    return ang;
8516 }
8517
8518 /* get proper rotation value using preferred rotation and list of available rotations */
8519 static int
8520 _e_border_rotation_get(E_Border *bd,
8521                        int       base_ang)
8522 {
8523    int ang = -1;
8524    int current_ang = bd->client.e.state.rot.curr;
8525    unsigned int i;
8526    Eina_Bool found = EINA_FALSE;
8527    Eina_Bool found_curr_ang = EINA_FALSE;
8528
8529    if (!e_config->wm_win_rotation) return ang;
8530    if (!bd->client.e.state.rot.app_set) return ang;
8531
8532    if (bd->client.e.state.rot.preferred_rot != -1)
8533      {
8534         ang = bd->client.e.state.rot.preferred_rot;
8535         ELBF(ELBT_ROT, 0, bd->client.win, "ang:%d base_ang:%d", ang, base_ang);
8536      }
8537    else if ((bd->client.e.state.rot.available_rots) &&
8538             (bd->client.e.state.rot.count))
8539      {
8540         for (i = 0; i < bd->client.e.state.rot.count; i++)
8541           {
8542              if (bd->client.e.state.rot.available_rots[i] == base_ang)
8543                {
8544                   ang = base_ang;
8545                   found = EINA_TRUE;
8546                   break;
8547                }
8548              if (bd->client.e.state.rot.available_rots[i] == current_ang)
8549                found_curr_ang = EINA_TRUE;
8550           }
8551
8552         /* do nothing. this window wants to maintain current state.
8553          * for example, window's available_rots: 0, 90, 270,
8554          * current zone rotation request: 180. the WM does nothing
8555          * for this window.
8556          */
8557         if (!found)
8558           {
8559              if ((bd->client.e.state.rot.curr != -1) && (found_curr_ang))
8560                ang = bd->client.e.state.rot.curr;
8561              else
8562                ang = bd->client.e.state.rot.available_rots[0];
8563           }
8564      }
8565    else
8566      {
8567         /* In this case, border doesn't have a list of
8568          * available rotations, thus WM should request
8569          * rotation with '0' degree to the application.
8570          */
8571         ang = 0;
8572      }
8573
8574    return ang;
8575 }
8576
8577 static int
8578 _e_border_rotation_angle_get(E_Border *bd)
8579 {
8580    E_Zone *zone = bd->zone;
8581    int will_ang = 0;
8582    int _ang = 0;
8583    int ret = -1;
8584
8585    if (!e_config->wm_win_rotation) return ret;
8586    if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) return ret;
8587
8588    ELB(ELBT_ROT, "CHECK ROT", bd->client.win);
8589
8590    // the window with "ECORE_X_WINDOW_TYPE_NORMAL" type
8591    // should follow the state of rotation of zone.
8592    if ((bd->parent) &&
8593        (bd->parent->visible) &&
8594        (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL))
8595      will_ang = bd->parent->client.e.state.rot.curr;
8596    else will_ang = zone->rot.curr;
8597
8598    if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
8599      {
8600         ELBF(ELBT_ROT, 1, bd->client.win,
8601              "%s->parent:0x%08x (support:%d app_set:%d ang:%d)",
8602              (rot.vkbd == bd) ? "vkbd" : "prediction",
8603              bd->parent ? bd->parent->client.win : 0,
8604              bd->parent ? bd->parent->client.e.state.rot.support : -1,
8605              bd->parent ? bd->parent->client.e.state.rot.app_set : -1,
8606              bd->parent ? bd->parent->client.e.state.rot.curr : -1);
8607
8608         if (bd->parent)
8609           {
8610              will_ang = bd->parent->client.e.state.rot.curr;
8611              if ((!bd->parent->client.e.state.rot.support) &&
8612                  (!bd->parent->client.e.state.rot.app_set))
8613                {
8614                   will_ang = 0;
8615                }
8616           }
8617      }
8618
8619    if ((!bd->client.e.state.rot.app_set) &&
8620        (!bd->client.e.state.rot.support))
8621      {
8622         /* hack for magnifier and keyboard popup */
8623         if ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER) ||
8624             (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP))
8625           {
8626              ELB(ELBT_BD, "MAG", bd->client.win);
8627              will_ang = 0;
8628              if ((rot.vkbd) && (rot.vkbd->visible))
8629                will_ang = rot.vkbd->client.e.state.rot.curr;
8630           }
8631      }
8632
8633    if (bd->client.e.state.rot.app_set)
8634      {
8635         /* utility type window should be rotated according to
8636          * rotation of the transient_for window.
8637          */
8638         if ((bd->parent) &&
8639             (bd->parent->visible) &&
8640             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
8641           {
8642              will_ang = bd->parent->client.e.state.rot.curr;
8643              if ((!bd->parent->client.e.state.rot.support) &&
8644                  (!bd->parent->client.e.state.rot.app_set))
8645                {
8646                   /* if transient_for window doesn't support rotation feature,
8647                    * then this window should't be rotated.
8648                    * TODO: need to check whether window supports '0' degree or not.
8649                    */
8650                   will_ang = 0;
8651                   ELBF(ELBT_ROT, 0, bd->client.win,
8652                        "GET ROT ang:%d Transient_For:0x%08x Not support rot",
8653                        will_ang, bd->parent->client.win);
8654                }
8655              else
8656                {
8657                   will_ang = _e_border_rotation_get(bd->parent, will_ang);
8658                   ELBF(ELBT_ROT, 0, bd->client.win,
8659                        "GET ROT ang:%d Transient_For:0x%08x",
8660                        will_ang, bd->parent->client.win);
8661                }
8662           }
8663         else
8664           {
8665              will_ang = _e_border_rotation_get(bd, will_ang);
8666              ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d",
8667                   will_ang, bd->parent ? bd->parent->client.win : 0,
8668                   bd->client.netwm.type);
8669           }
8670      }
8671
8672    if (bd->new_client)
8673      {
8674         _ang = _prev_angle_get(bd->client.win);
8675         if (_ang != -1)
8676           bd->client.e.state.rot.curr = _ang;
8677         ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang);
8678      }
8679
8680    if (bd->client.e.state.rot.curr != will_ang)
8681      ret = will_ang;
8682
8683    return ret;
8684 }
8685
8686
8687 static Eina_Bool
8688 _e_border_rotation_zone_set(E_Zone *zone)
8689 {
8690    E_Border_List *l = NULL;
8691    E_Border *bd = NULL;
8692    Eina_Bool ret = EINA_FALSE;
8693
8694    if (!e_config->wm_win_rotation) return EINA_FALSE;
8695
8696    l = e_container_border_list_last(zone->container);
8697    if (!l) return ret;
8698
8699    /* step 1. make the list needs to be rotated. */
8700    while ((bd = e_container_border_list_prev(l)))
8701      {
8702         if (!bd) continue;
8703
8704         // if this window has parent and window type isn't "ECORE_X_WINDOW_TYPE_NORMAL",
8705         // it will be rotated when parent do rotate itself.
8706         // so skip here.
8707         if ((bd->parent) &&
8708             (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL)) continue;
8709
8710         // default type is "E_BORDER_ROTATION_TYPE_NORMAL",
8711         // but it can be changed to "E_BORDER_ROTATION_TYPE_DEPENDENT" by illume according to its policy.
8712         // if it's not normal type window, will be rotated by illume.
8713         // so skip here.
8714         if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue;
8715
8716         if ((!bd->visible) ||
8717             (!E_INTERSECTS(bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h,
8718                            bd->x, bd->y, bd->w, bd->h))) continue;
8719
8720         if (_e_border_rotatable_check(bd, zone->rot.curr))
8721           {
8722              ELBF(ELBT_ROT, 0, bd->client.win, "ROT_SET(main) curr:%d != TOBE:%d",
8723                   bd->client.e.state.rot.curr, zone->rot.curr);
8724
8725              ret = e_border_rotation_set(bd, zone->rot.curr);
8726           }
8727      }
8728    if (l) e_container_border_list_free(l);
8729
8730    return ret;
8731 }
8732
8733 static Eina_Bool
8734 _e_border_rotation_set_internal(E_Border *bd, int rotation, Eina_Bool *pending)
8735 {
8736    E_Zone *zone = bd->zone;
8737    E_Border_Rotation_Info *info = NULL;
8738    Eina_List *list, *l;
8739    E_Border *child;
8740
8741    if (rotation < 0) return EINA_FALSE;
8742    if (pending) *pending = EINA_FALSE;
8743
8744    /* step 1. check if rotation */
8745    if (!_e_border_rotatable_check(bd, rotation)) return EINA_FALSE;
8746
8747    /* step 2. add to async/sync list */
8748    if ((!zone->rot.block_count) &&
8749        (!bd->client.e.state.deiconify_approve.pending_bd) &&
8750        ((!bd->visible) ||
8751         (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))))
8752      {
8753         // send rotation change request later.
8754         // and no need to wait message of rotation done.
8755
8756         // async list add
8757         info = E_NEW(E_Border_Rotation_Info, 1);
8758         if (!info) return EINA_FALSE;
8759         ELB(ELBT_ROT, "ADD ASYNC LIST", 0);
8760         info->bd = bd;
8761         info->ang = rotation;
8762         rot.async_list = eina_list_append(rot.async_list, info);
8763
8764         // add job for sending event.
8765         if (!rot.async_job)
8766           {
8767              ELB(ELBT_ROT, "ADD ASYNC_JOB", bd->client.win);
8768              rot.async_job = ecore_job_add(_e_border_cb_rotation_async_job, zone);
8769           }
8770      }
8771    else
8772      {
8773         // sync list add
8774         info = E_NEW(E_Border_Rotation_Info, 1);
8775         if (!info) return EINA_FALSE;
8776         ELB(ELBT_ROT, "ADD SYNC LIST", 0);
8777         info->bd = bd;
8778         info->ang = rotation;
8779         rot.list = eina_list_append(rot.list, info);
8780
8781         // add job for sending event.
8782         if (!rot.sync_job)
8783           {
8784              ELB(ELBT_ROT, "ADD SYNC_JOB", bd->client.win);
8785              rot.sync_job = ecore_job_add(_e_border_cb_rotation_sync_job, zone);
8786           }
8787
8788         // if there is windows over 2 that has to be rotated or is existed window needs resizing,
8789         // lock the screen.
8790         // but, DO NOT lock the screen when rotation block state.
8791         if ((!zone->rot.block_count) &&
8792             ((eina_list_count(rot.list) == 2)))
8793           e_manager_comp_screen_lock(e_manager_current_get());
8794      }
8795
8796    if (pending) *pending = EINA_TRUE;
8797
8798    /* step 3. search rotatable window in this window's child */
8799    list = _e_border_sub_borders_new(bd);
8800    EINA_LIST_FOREACH(list, l, child)
8801      {
8802         // the window which type is "ECORE_X_WINDOW_TYPE_NORMAL" will be rotated itself.
8803         // it shouldn't be rotated by rotation state of parent window.
8804         if (child->client.netwm.type == ECORE_X_WINDOW_TYPE_NORMAL) continue;
8805         if (_e_border_rotatable_check(child, rotation))
8806           {
8807              ELBF(ELBT_ROT, 0, child->client.win, "ROT_SET(child) curr:%d != TOBE:%d",
8808                   bd->client.e.state.rot.curr, rotation);
8809              e_border_rotation_set(child, rotation);
8810           }
8811      }
8812
8813    /* step 4. if there is vkbd window, send message to prepare rotation */
8814    if (_e_border_is_vkbd(bd))
8815      {
8816         ELB(ELBT_ROT, "PENDING ROT_REQ UNTIL GET PREP_DONE", rot.vkbd_ctrl_win);
8817         if (rot.prepare_timer)
8818           ecore_timer_del(rot.prepare_timer);
8819         rot.prepare_timer = NULL;
8820
8821         if (rot.done_timer)
8822           ecore_timer_del(rot.done_timer);
8823         rot.done_timer = NULL;
8824
8825         ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win);
8826         ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8827                                                       zone->rot.curr,
8828                                                       EINA_FALSE, 1, 1);
8829         rot.prepare_timer = ecore_timer_add(4.0f,
8830                                             _e_border_rotation_change_prepare_timeout,
8831                                             NULL);
8832
8833         rot.wait_prepare_done = EINA_TRUE;
8834      }
8835
8836    bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8837    bd->client.e.state.rot.curr = rotation;
8838
8839    return EINA_TRUE;
8840 }
8841
8842 // check if border is rotatable in ang.
8843 static Eina_Bool
8844 _e_border_rotatable_check(E_Border *bd, int ang)
8845 {
8846    Eina_Bool ret = EINA_FALSE;
8847
8848    if (!bd) return ret;
8849    if (ang < 0) return ret;
8850    if ((!bd->client.e.state.rot.support) && (!bd->client.e.state.rot.app_set)) return ret;
8851    if (e_object_is_del(E_OBJECT(bd))) return ret;
8852
8853    // same with current angle of window, then false return.
8854    if (ang == bd->client.e.state.rot.curr) return ret;
8855
8856    /* basically WM allows only fullscreen window to rotate */
8857    if (bd->client.e.state.rot.preferred_rot == -1)
8858      {
8859         unsigned int i;
8860
8861         if (bd->client.e.state.rot.app_set)
8862           {
8863              if (bd->client.e.state.rot.available_rots &&
8864                  bd->client.e.state.rot.count)
8865                {
8866                   Eina_Bool found = EINA_FALSE;
8867                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8868                     {
8869                        if (bd->client.e.state.rot.available_rots[i] == ang)
8870                          {
8871                             found = EINA_TRUE;
8872                          }
8873                     }
8874                   if (found) ret = EINA_TRUE;
8875                }
8876           }
8877         else
8878           {
8879              ELB(ELBT_ROT, "DO ROT", 0);
8880              ret = EINA_TRUE;
8881           }
8882      }
8883    // if it has preferred rotation angle,
8884    // it will be rotated at border's evaluation time.
8885    // so skip it.
8886    else if (bd->client.e.state.rot.preferred_rot == ang) ret = EINA_TRUE;
8887
8888    return ret;
8889 }
8890
8891 /* check whether virtual keyboard is visible on the zone */
8892 static Eina_Bool
8893 _e_border_is_vkbd(E_Border *bd)
8894 {
8895    if (!e_config->wm_win_rotation) return EINA_FALSE;
8896
8897    if ((rot.vkbd_ctrl_win) &&
8898        (rot.vkbd == bd) &&
8899        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8900        (rot.vkbd->zone == bd->zone) &&
8901        (E_INTERSECTS(bd->zone->x, bd->zone->y,
8902                      bd->zone->w, bd->zone->h,
8903                      rot.vkbd->x, rot.vkbd->y,
8904                      rot.vkbd->w, rot.vkbd->h)))
8905      {
8906         return EINA_TRUE;
8907      }
8908    return EINA_FALSE;
8909 }
8910
8911 static Eina_Bool
8912 _e_border_rotation_change_floating_pos(E_Border *bd, int *x, int *y)
8913 {
8914    int new_x, new_y;
8915    int min_title_width=96;
8916
8917    if (!bd) return EINA_FALSE;
8918    if (!x || !y) return EINA_FALSE;
8919
8920    new_x = bd->x;
8921    new_y = bd->y;
8922
8923    // Portrait -> Landscape,  x= pre_x*2, y=pre_y/2
8924    // Landscape -> Portrait,  x= pre_x/2, y=pre_y*2
8925    // guaranteeing the minimum size of titlebar shown, min_title_width
8926    // so user can initiate drag&drop action after rotation changed.
8927    if (bd->client.e.state.rot.curr == 0)
8928      {
8929         if (bd->client.e.state.rot.prev == 90)
8930           {
8931              new_x = (bd->zone->h - bd->h - bd->y) / 2;
8932              new_y = 2 * bd->x;
8933           }
8934         else if (bd->client.e.state.rot.prev == 270)
8935           {
8936              new_x = bd->y / 2;
8937              new_y = (bd->zone->w - bd->w - bd->x) * 2;
8938           }
8939         else if (bd->client.e.state.rot.prev == 180)
8940           {
8941              new_x = bd->zone->w - bd->x - bd->w;
8942              new_y = bd->zone->h - bd->y - bd->h;
8943           }
8944
8945         if(new_x + bd->w < min_title_width)
8946           {
8947              new_x = min_title_width - bd->w;
8948           }
8949         else if(new_x > bd->zone->w - min_title_width)
8950           {
8951              new_x = bd->zone->w - min_title_width;
8952           }
8953      }
8954    else if (bd->client.e.state.rot.curr == 90)
8955      {
8956         if (bd->client.e.state.rot.prev == 0)
8957           {
8958              new_x = bd->y / 2;
8959              new_y = bd->zone->h - (2 * bd->x) - bd->w;
8960           }
8961         else if (bd->client.e.state.rot.prev == 270)
8962           {
8963              new_x = bd->zone->w - bd->x - bd->w;
8964              new_y = bd->zone->h - bd->y - bd->h;
8965           }
8966         else if (bd->client.e.state.rot.prev == 180)
8967           {
8968              new_x = (bd->zone->h - bd->y - bd->h) / 2;
8969              new_y = bd->zone->h - (2 * (bd->zone->w - bd->x - bd->w)) - bd->w;
8970           }
8971
8972         if(new_y > bd->zone->h - min_title_width)
8973           {
8974              new_y = bd->zone->h - min_title_width;
8975           }
8976         else if(new_y < min_title_width - bd->w)
8977           {
8978              new_y = min_title_width - bd->w;
8979           }
8980      }
8981    else if (bd->client.e.state.rot.curr == 270)
8982      {
8983         if (bd->client.e.state.rot.prev == 0)
8984           {
8985              new_x = bd->zone->w - bd->h - (bd->y / 2);
8986              new_y = bd->x * 2;
8987           }
8988         else if (bd->client.e.state.rot.prev == 90)
8989           {
8990              new_x = bd->zone->w - bd->x - bd->w;
8991              new_y = bd->zone->h - bd->y - bd->h;
8992           }
8993         else if (bd->client.e.state.rot.prev == 180)
8994           {
8995              new_x = bd->zone->w - bd->x - bd->w;
8996              new_y = bd->zone->h - bd->y - bd->h;
8997
8998              new_x = bd->zone->w - bd->h - ((bd->zone->h - bd->y - bd->h) / 2);
8999              new_y = (bd->zone->w - bd->x - bd->w) * 2;
9000           }
9001
9002         if(new_y >  bd->zone->h - min_title_width)
9003           {
9004              new_y = bd->zone->h - min_title_width;
9005           }
9006         else if( new_y + bd->w < min_title_width)
9007           {
9008              new_y = min_title_width - bd->w ;
9009           }
9010      }
9011    else if (bd->client.e.state.rot.curr == 180)
9012      {
9013         if (bd->client.e.state.rot.prev == 0)
9014           {
9015              new_x = bd->zone->w - bd->x - bd->w;
9016              new_y = bd->zone->h - bd->y - bd->h;
9017           }
9018         else if (bd->client.e.state.rot.prev == 90)
9019           {
9020              new_x = bd->zone->w - ((bd->zone->h - bd->h - bd->y) / 2) - bd->h;
9021              new_y = bd->zone->h - (2 * bd->x) - bd->w;
9022           }
9023         else if (bd->client.e.state.rot.prev == 270)
9024           {
9025              new_x = bd->zone->w - (bd->y / 2) - bd->h;
9026              new_y = bd->zone->h - ((bd->zone->w - bd->w - bd->x) * 2) - bd->w;
9027           }
9028
9029         if(new_x + bd->w < min_title_width)
9030           {
9031              new_x = min_title_width - bd->w;
9032           }
9033         else if(new_x > bd->zone->w - min_title_width)
9034           {
9035              new_x = bd->zone->w - min_title_width;
9036           }
9037      }
9038
9039    ELBF(ELBT_ROT, 0, bd->client.win,
9040         "Floating Mode. ANGLE (%d->%d), POS (%d,%d) -> (%d,%d)",
9041         bd->client.e.state.rot.prev, bd->client.e.state.rot.curr,
9042         bd->x, bd->y, new_x, new_y);
9043
9044    if ((new_x == *x) &&
9045        (new_y == *y))
9046      {
9047         return EINA_FALSE;
9048      }
9049
9050    *x = new_x;
9051    *y = new_y;
9052
9053    return EINA_TRUE;
9054 }
9055
9056 #define SIZE_EQUAL_TO_ZONE(a, z) \
9057    ((((a)->w) == ((z)->w)) &&    \
9058     (((a)->h) == ((z)->h)))
9059 static Eina_Bool
9060 _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h)
9061 {
9062    E_Zone *zone = bd->zone;
9063    int rot_dif;
9064    int _x, _y, _w, _h;
9065    Eina_Bool move = EINA_FALSE;
9066    Eina_Bool hint = EINA_FALSE;
9067    Eina_Bool resize = EINA_FALSE;
9068
9069    if (x) *x = bd->x;
9070    if (y) *y = bd->y;
9071    if (w) *w = bd->w;
9072    if (h) *h = bd->h;
9073
9074    if (SIZE_EQUAL_TO_ZONE(bd, zone)) return resize;
9075
9076    ELB(ELBT_ROT, "SIZE DIFF WITH ZONE", 0);
9077    ELBF(ELBT_ROT, 0, bd->client.win, "ORIGIN_SIZE name:%s (%d,%d) %dx%d",
9078         bd->client.icccm.name, bd->x, bd->y, bd->w, bd->h);
9079
9080    hint = _e_border_rotation_geom_get(bd, bd->zone, rotation,
9081                                       &_x, &_y, &_w, &_h, &move);
9082    if (hint)
9083      {
9084         if (((move) && ((bd->x !=_x) || (bd->y !=_y))) ||
9085             (bd->w != _w) || (bd->h != _h))
9086           {
9087              resize = EINA_TRUE;
9088              _e_border_move_resize_internal(bd, _x, _y, _w, _h, EINA_TRUE, move);
9089              ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d resize:%d",
9090                   bd->client.icccm.name, _x, _y, _w, _h, resize);
9091           }
9092      }
9093    else
9094      {
9095         _x = bd->x; _y = bd->y;
9096         _w = bd->w; _h = bd->h;
9097
9098         if (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)
9099           move = _e_border_rotation_change_floating_pos(bd, &_x, &_y);
9100         else
9101           move = EINA_FALSE;
9102
9103         rot_dif = bd->client.e.state.rot.prev - rotation;
9104         if (rot_dif < 0) rot_dif = -rot_dif;
9105         if (rot_dif != 180)
9106           {
9107              if (_w != _h)
9108                {
9109                   _w = bd->h;
9110                   _h = bd->w;
9111                   resize = EINA_TRUE;
9112
9113                   _e_border_move_resize_internal(bd, _x, _y, _w, _h,
9114                                                  EINA_TRUE, EINA_TRUE);
9115                   ELBF(ELBT_ROT, 0, bd->client.win, "MANUAL_RESIZE name:%s (%d,%d) %dx%d",
9116                        bd->client.icccm.name, _x, _y, _w, _h);
9117
9118                }
9119           }
9120
9121         if (!resize && move)
9122           _e_border_move_internal(bd, _x, _y, EINA_TRUE);
9123      }
9124
9125    if (resize)
9126      {
9127         if (x) *x = _x;
9128         if (y) *y = _y;
9129         if (w) *w = _w;
9130         if (h) *h = _h;
9131      }
9132
9133    return resize;
9134 }
9135
9136 static Eina_Bool
9137 _e_border_cb_window_configure(void *data    __UNUSED__,
9138                               int   ev_type __UNUSED__,
9139                               void         *ev)
9140 {
9141    Ecore_X_Event_Window_Configure *e = ev;
9142    E_Border_Rotation_Info *info = NULL;
9143    Eina_List *l;
9144    Eina_Bool found = EINA_FALSE;
9145
9146    if (!e) return ECORE_CALLBACK_PASS_ON;
9147    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
9148
9149    E_Border *bd = e_border_find_by_client_window(e->win);
9150    if (!bd) return ECORE_CALLBACK_PASS_ON;
9151
9152    if (bd->client.e.state.rot.pending_change_request)
9153      {
9154         if ((e->w == bd->w) && (e->h == bd->h))
9155           {
9156              ELB(ELBT_BD, "GET CONFIGURE_NOTI (ROTATION)", bd->client.win);
9157              bd->client.e.state.rot.pending_change_request = 0;
9158
9159              if ((bd->client.e.state.rot.wait_for_done) &&
9160                  (bd->client.e.state.rot.wait_done_ang == bd->client.e.state.rot.curr)) goto end;
9161
9162              EINA_LIST_FOREACH(rot.list, l, info)
9163                 if (info->bd == bd) found = EINA_TRUE;
9164              // send request message if it's async rotation window,
9165              // even if wait prepare done.
9166              if ((found) && (rot.wait_prepare_done)) goto end;
9167
9168              ELBF(ELBT_ROT, 0, bd->client.win,
9169                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
9170                   bd->client.e.state.rot.curr,
9171                   bd->w, bd->h);
9172 #ifdef _F_USE_DLOG_
9173              SECURE_SLOGD("[ROTATION] SEND REQ_ROT(CONFIGURE_NOTI), win:0x%08x, rot:%d",
9174                           bd->client.win, bd->client.e.state.rot.curr);
9175 #endif
9176              ecore_x_e_window_rotation_change_request_send(bd->client.win,
9177                                                            bd->client.e.state.rot.curr);
9178              bd->client.e.state.rot.wait_for_done = 1;
9179              bd->client.e.state.rot.wait_done_ang = bd->client.e.state.rot.curr;
9180           }
9181      }
9182
9183 end:
9184    return ECORE_CALLBACK_PASS_ON;
9185 }
9186
9187 static Eina_Bool
9188 _e_border_rotation_geom_get(E_Border  *bd,
9189                             E_Zone    *zone,
9190                             int        ang,
9191                             int       *x,
9192                             int       *y,
9193                             int       *w,
9194                             int       *h,
9195                             Eina_Bool *move)
9196 {
9197    if (!e_config->wm_win_rotation) return EINA_FALSE;
9198
9199    Eina_Bool res = EINA_FALSE;
9200    Eina_Bool _move = EINA_TRUE;
9201    int _x = bd->x;
9202    int _y = bd->y;
9203    int _w = bd->w;
9204    int _h = bd->h;
9205
9206    if (x) *x = bd->x;
9207    if (y) *y = bd->y;
9208    if (w) *w = bd->w;
9209    if (h) *h = bd->h;
9210    if (move) *move = EINA_TRUE;
9211
9212    if (bd->client.e.state.rot.geom_hint)
9213      {
9214         switch (ang)
9215           {
9216            case   0:
9217               _w = bd->client.e.state.rot.geom[0].w;
9218               _h = bd->client.e.state.rot.geom[0].h;
9219               if (_w == 0) _w = bd->w;
9220               if (_h == 0) _h = bd->h;
9221               _x = 0; _y = zone->h - _h;
9222               break;
9223            case  90:
9224               _w = bd->client.e.state.rot.geom[1].w;
9225               _h = bd->client.e.state.rot.geom[1].h;
9226               if (_w == 0) _w = bd->w;
9227               if (_h == 0) _h = bd->h;
9228               _x = zone->w - _w; _y = 0;
9229               break;
9230            case 180:
9231               _w = bd->client.e.state.rot.geom[2].w;
9232               _h = bd->client.e.state.rot.geom[2].h;
9233               if (_w == 0) _w = bd->w;
9234               if (_h == 0) _h = bd->h;
9235               _x = 0; _y = 0;
9236               break;
9237            case 270:
9238               _w = bd->client.e.state.rot.geom[3].w;
9239               _h = bd->client.e.state.rot.geom[3].h;
9240               if (_w == 0) _w = bd->w;
9241               if (_h == 0) _h = bd->h;
9242               _x = 0; _y = 0;
9243               break;
9244           }
9245
9246         if (x) *x = _x;
9247         if (y) *y = _y;
9248         if (w) *w = _w;
9249         if (h) *h = _h;
9250
9251         if (!((rot.vkbd) && (rot.vkbd == bd)))
9252           {
9253              if (x) *x = bd->x;
9254              if (y) *y = bd->y;
9255              if (move) *move = EINA_FALSE;
9256           }
9257
9258         res = EINA_TRUE;
9259      }
9260
9261    if (res)
9262      {
9263         _x = 0; _y = 0; _w = 0; _h = 0;
9264         if (x) _x = *x;
9265         if (y) _y = *y;
9266         if (w) _w = *w;
9267         if (h) _h = *h;
9268         if (move) _move = *move;
9269
9270         ELBF(ELBT_ROT, 1, bd->client.win,
9271              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
9272              ang, _x, _y, _w, _h, _move);
9273      }
9274
9275    return res;
9276 }
9277 #endif
9278
9279 static Eina_Bool
9280 _e_border_post_move_resize_job(void *data)
9281 {
9282    E_Border *bd;
9283
9284    bd = (E_Border *)data;
9285    if (bd->post_move)
9286      {
9287         E_Border *tmp;
9288         Eina_List *l;
9289
9290         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
9291           ecore_x_window_move(tmp->win,
9292                               bd->x +
9293                               bd->client_inset.l +
9294                               bd->fx.x +
9295                               tmp->client.e.state.video_position.x,
9296                               bd->y +
9297                               bd->client_inset.t +
9298                               bd->fx.y +
9299                               tmp->client.e.state.video_position.y);
9300      }
9301    if (bd->client.e.state.video)
9302      {
9303         E_Border *parent;
9304
9305         parent = bd->client.e.state.video_parent_border;
9306         ecore_x_window_move(bd->win,
9307                             parent->x +
9308                             parent->client_inset.l +
9309                             parent->fx.x +
9310                             bd->client.e.state.video_position.x,
9311                             parent->y +
9312                             parent->client_inset.t +
9313                             parent->fx.y +
9314                             bd->client.e.state.video_position.y);
9315      }
9316    else if ((bd->post_move) && (bd->post_resize))
9317      {
9318         ecore_x_window_move_resize(bd->win,
9319                                    bd->x + bd->fx.x,
9320                                    bd->y + bd->fx.y,
9321                                    bd->w, bd->h);
9322      }
9323    else if (bd->post_move)
9324      {
9325         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
9326      }
9327    else if (bd->post_resize)
9328      {
9329         ecore_x_window_resize(bd->win, bd->w, bd->h);
9330      }
9331
9332    if (bd->client.e.state.video)
9333      {
9334         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
9335                 bd->win,
9336                 bd->client.e.state.video_parent_border->x +
9337                 bd->client.e.state.video_parent_border->client_inset.l +
9338                 bd->client.e.state.video_parent_border->fx.x +
9339                 bd->client.e.state.video_position.x,
9340                 bd->client.e.state.video_parent_border->y +
9341                 bd->client.e.state.video_parent_border->client_inset.t +
9342                 bd->client.e.state.video_parent_border->fx.y +
9343                 bd->client.e.state.video_position.y,
9344                 bd->w, bd->h);
9345      }
9346
9347    if (bd->post_show)
9348      {
9349         if (bd->visible)
9350           {
9351              bd->post_job = NULL;
9352              _e_border_show(bd);
9353           }
9354      }
9355    bd->post_show = 0;
9356    bd->post_move = 0;
9357    bd->post_resize = 0;
9358    bd->post_job = NULL;
9359    return ECORE_CALLBACK_CANCEL;
9360 }
9361
9362 static void
9363 _e_border_container_layout_hook(E_Container *con)
9364 {
9365    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
9366 }
9367
9368 static void
9369 _e_border_eval0(E_Border *bd)
9370 {
9371    int change_urgent = 0;
9372    int rem_change = 0;
9373 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9374    Eina_Bool need_desk_set = EINA_FALSE;
9375 #endif
9376 #ifdef _F_ZONE_WINDOW_ROTATION_
9377    Eina_Bool need_rotation_set = EINA_FALSE;
9378
9379    if ((e_config->wm_win_rotation) &&
9380        (bd->client.icccm.fetch.transient_for))
9381      {
9382         if (((rot.vkbd) && (rot.vkbd == bd)) ||
9383             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
9384           {
9385              need_rotation_set = EINA_TRUE;
9386              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
9387           }
9388      }
9389 #endif
9390
9391    if (e_object_is_del(E_OBJECT(bd)))
9392      {
9393         CRI("_e_border_eval(%p) with deleted border!\n", bd);
9394         bd->changed = 0;
9395         return;
9396      }
9397
9398    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
9399
9400    bd->changes.border = 0;
9401
9402    /* fetch any info queued to be fetched */
9403    if (bd->client.netwm.fetch.state)
9404      {
9405         e_hints_window_state_get(bd);
9406         bd->client.netwm.fetch.state = 0;
9407         rem_change = 1;
9408      }
9409    if (bd->client.icccm.fetch.client_leader)
9410      {
9411         /* TODO: What do to if the client leader isn't mapped yet? */
9412         E_Border *bd_leader = NULL;
9413
9414         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
9415         if (bd->client.icccm.client_leader)
9416           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
9417         if (bd->leader)
9418           {
9419              if (bd->leader != bd_leader)
9420                {
9421                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
9422                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
9423                   bd->leader = NULL;
9424                }
9425              else
9426                bd_leader = NULL;
9427           }
9428         /* If this border is the leader of the group, don't register itself */
9429         if ((bd_leader) && (bd_leader != bd))
9430           {
9431              bd_leader->group = eina_list_append(bd_leader->group, bd);
9432              bd->leader = bd_leader;
9433              /* Only set the window modal to the leader it there is no parent */
9434              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
9435                  ((!bd->parent) || (bd->parent->modal != bd)))
9436                {
9437                   bd->leader->modal = bd;
9438                   if (bd->leader->focused)
9439                     e_border_focus_set(bd, 1, 1);
9440                   else
9441                     {
9442                        Eina_List *l;
9443                        E_Border *child;
9444
9445                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9446                          {
9447                             if ((child != bd) && (child->focused))
9448                               e_border_focus_set(bd, 1, 1);
9449                          }
9450                     }
9451                }
9452           }
9453         bd->client.icccm.fetch.client_leader = 0;
9454         rem_change = 1;
9455      }
9456    if (bd->client.icccm.fetch.title)
9457      {
9458         char *title = ecore_x_icccm_title_get(bd->client.win);
9459         eina_stringshare_replace(&bd->client.icccm.title, title);
9460         if (title) free(title);
9461
9462         if (bd->bg_object)
9463           edje_object_part_text_set(bd->bg_object, "e.text.title",
9464                                     bd->client.icccm.title);
9465         bd->client.icccm.fetch.title = 0;
9466         rem_change = 1;
9467      }
9468    if (bd->client.netwm.fetch.name)
9469      {
9470         char *name;
9471         ecore_x_netwm_name_get(bd->client.win, &name);
9472         eina_stringshare_replace(&bd->client.netwm.name, name);
9473         if (name) free(name);
9474
9475         if (bd->bg_object)
9476           edje_object_part_text_set(bd->bg_object, "e.text.title",
9477                                     bd->client.netwm.name);
9478         bd->client.netwm.fetch.name = 0;
9479         rem_change = 1;
9480      }
9481    if (bd->client.icccm.fetch.name_class)
9482      {
9483         const char *pname, *pclass;
9484         char *nname, *nclass;
9485
9486         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
9487         pname = bd->client.icccm.name;
9488         pclass = bd->client.icccm.class;
9489         bd->client.icccm.name = eina_stringshare_add(nname);
9490         bd->client.icccm.class = eina_stringshare_add(nclass);
9491         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
9492           e_bindings_mapping_change_enable(EINA_FALSE);
9493 #ifdef _F_ZONE_WINDOW_ROTATION_
9494         if (e_config->wm_win_rotation)
9495           {
9496              if ((bd->client.icccm.name) && (bd->client.icccm.class))
9497                {
9498                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
9499                       (!strcmp(bd->client.icccm.class, "ISF")))
9500                     {
9501                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
9502                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
9503                        rot.vkbd = bd;
9504                     }
9505                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
9506                            (!strcmp(bd->client.icccm.class, "ISF")))
9507                     {
9508                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
9509                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
9510                        rot.vkbd_prediction = bd;
9511                     }
9512                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
9513                            (!strcmp(bd->client.icccm.class, "ISF")))
9514                     {
9515                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
9516                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
9517                     }
9518                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
9519                            (!strcmp(bd->client.icccm.class, "ISF")))
9520                     {
9521                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
9522                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
9523                     }
9524                }
9525           }
9526 #endif
9527         if (nname) free(nname);
9528         if (nclass) free(nclass);
9529
9530         if (!((bd->client.icccm.name == pname) &&
9531               (bd->client.icccm.class == pclass)))
9532           bd->changes.icon = 1;
9533
9534         if (pname) eina_stringshare_del(pname);
9535         if (pclass) eina_stringshare_del(pclass);
9536         bd->client.icccm.fetch.name_class = 0;
9537         bd->changes.icon = 1;
9538         rem_change = 1;
9539      }
9540    if (bd->client.icccm.fetch.state)
9541      {
9542         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
9543         bd->client.icccm.fetch.state = 0;
9544         rem_change = 1;
9545      }
9546    if (bd->client.e.fetch.state)
9547      {
9548         e_hints_window_e_state_get(bd);
9549         bd->client.e.fetch.state = 0;
9550         rem_change = 1;
9551      }
9552 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9553    if (bd->client.e.fetch.profile_list)
9554      {
9555         const char **profiles = NULL;
9556         const char *str;
9557         int num = 0, i;
9558
9559         if (bd->client.e.state.profile)
9560           eina_stringshare_del(bd->client.e.state.profile);
9561         EINA_LIST_FREE(bd->client.e.state.profiles, str)
9562           {
9563              if (str) eina_stringshare_del(str);
9564           }
9565         bd->client.e.state.profile = NULL;
9566         bd->client.e.state.profiles = NULL;
9567         bd->client.e.state.profile_list = 0;
9568
9569         if (ecore_x_e_window_profile_list_get(bd->client.win,
9570                                               &profiles, &num))
9571           {
9572              bd->client.e.state.profile_list = 1;
9573              for (i = 0; i < num; i++)
9574                {
9575                   str = eina_stringshare_add(profiles[i]);
9576                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
9577                }
9578
9579              /* We should set desk to contain given border after creating E_BORDER_ADD event.
9580               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
9581               */
9582              need_desk_set = EINA_TRUE;
9583           }
9584         else
9585           {
9586              if (strcmp(bd->desk->window_profile,
9587                         e_config->desktop_default_window_profile) != 0)
9588                {
9589                   ecore_x_e_window_profile_set(bd->client.win,
9590                                                bd->desk->window_profile);
9591                }
9592           }
9593
9594         if (profiles)
9595           {
9596              for (i = 0; i < num; i++)
9597                 if (profiles[i]) free(profiles[i]);
9598              free(profiles);
9599           }
9600
9601         bd->client.e.fetch.profile_list = 0;
9602      }
9603 #endif
9604 #ifdef _F_ZONE_WINDOW_ROTATION_
9605    if ((e_config->wm_win_rotation) &&
9606        (bd->client.e.fetch.rot.support))
9607      {
9608         int ret = 0;
9609         unsigned int support = 0;
9610
9611         ret = ecore_x_window_prop_card32_get
9612           (bd->client.win,
9613           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
9614           &support, 1);
9615
9616         bd->client.e.state.rot.support = 0;
9617         if ((ret == 1) && (support == 1))
9618           bd->client.e.state.rot.support = 1;
9619
9620         if (bd->client.e.state.rot.support)
9621           need_rotation_set = EINA_TRUE;
9622
9623         bd->client.e.fetch.rot.support = 0;
9624      }
9625    if ((e_config->wm_win_rotation) &&
9626        (bd->client.e.fetch.rot.geom_hint))
9627      {
9628         Eina_Rectangle r[4];
9629         int i, x, y, w, h;
9630         bd->client.e.state.rot.geom_hint = 0;
9631         for (i = 0; i < 4; i++)
9632           {
9633              r[i].x = bd->client.e.state.rot.geom[i].x;
9634              r[i].y = bd->client.e.state.rot.geom[i].y;
9635              r[i].w = bd->client.e.state.rot.geom[i].w;
9636              r[i].h = bd->client.e.state.rot.geom[i].h;
9637
9638              bd->client.e.state.rot.geom[i].x = 0;
9639              bd->client.e.state.rot.geom[i].y = 0;
9640              bd->client.e.state.rot.geom[i].w = 0;
9641              bd->client.e.state.rot.geom[i].h = 0;
9642           }
9643
9644         for (i = 0; i < 4; i++)
9645           {
9646              x = 0; y = 0; w = 0; h = 0;
9647              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
9648                {
9649                   bd->client.e.state.rot.geom_hint = 1;
9650                   bd->client.e.state.rot.geom[i].x = x;
9651                   bd->client.e.state.rot.geom[i].y = y;
9652                   bd->client.e.state.rot.geom[i].w = w;
9653                   bd->client.e.state.rot.geom[i].h = h;
9654
9655                   if (!((r[i].x == x) && (r[i].y == y) &&
9656                         (r[i].w == w) && (r[i].h == h)))
9657                     {
9658                        need_rotation_set = EINA_TRUE;
9659                     }
9660                }
9661           }
9662         bd->client.e.fetch.rot.geom_hint = 0;
9663      }
9664    if ((e_config->wm_win_rotation) &&
9665        (bd->client.e.fetch.rot.app_set))
9666      {
9667         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
9668         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
9669         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
9670
9671         if (_prev_app_set != bd->client.e.state.rot.app_set)
9672           need_rotation_set = EINA_TRUE;
9673
9674         bd->client.e.fetch.rot.app_set = 0;
9675      }
9676    if ((e_config->wm_win_rotation) &&
9677        (bd->client.e.fetch.rot.preferred_rot))
9678      {
9679         int r = 0, _prev_preferred_rot;
9680         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
9681         bd->client.e.state.rot.preferred_rot = -1;
9682         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
9683           {
9684              bd->client.e.state.rot.preferred_rot = r;
9685              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
9686           }
9687         else
9688           {
9689              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
9690           }
9691
9692         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
9693           need_rotation_set = EINA_TRUE;
9694
9695         bd->client.e.fetch.rot.preferred_rot = 0;
9696      }
9697    if ((e_config->wm_win_rotation) &&
9698        (bd->client.e.fetch.rot.available_rots))
9699      {
9700         Eina_Bool res, diff = EINA_FALSE;
9701         int *rots = NULL;
9702         unsigned int count = 0, i = 0;
9703         int _prev_rots[4] = { -1, };
9704
9705         if (bd->client.e.state.rot.available_rots)
9706           {
9707              memcpy(_prev_rots,
9708                     bd->client.e.state.rot.available_rots,
9709                     (sizeof(int) * bd->client.e.state.rot.count));
9710
9711              E_FREE(bd->client.e.state.rot.available_rots);
9712           }
9713
9714         bd->client.e.state.rot.count = 0;
9715
9716         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
9717                                                                 &rots, &count);
9718         if ((res) && (count > 0) && (rots))
9719           {
9720              bd->client.e.state.rot.available_rots = rots;
9721              bd->client.e.state.rot.count = count;
9722
9723              for (i = 0; i < count; i++)
9724                {
9725                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
9726                   if ((!diff) && (_prev_rots[i] != rots[i]))
9727                     {
9728                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
9729                             count, i, _prev_rots[i], rots[i]);
9730                        diff = EINA_TRUE;
9731                     }
9732                }
9733           }
9734         else
9735           {
9736              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9737              diff = EINA_TRUE;
9738           }
9739
9740         if (diff) need_rotation_set = EINA_TRUE;
9741         bd->client.e.fetch.rot.available_rots = 0;
9742      }
9743 #endif
9744    if (bd->client.netwm.fetch.type)
9745      {
9746         e_hints_window_type_get(bd);
9747         if ((!bd->lock_border) || (!bd->client.border.name))
9748           bd->client.border.changed = 1;
9749
9750         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9751           {
9752              if (!bd->client.netwm.state.skip_pager)
9753                {
9754                   bd->client.netwm.state.skip_pager = 1;
9755                   bd->client.netwm.update.state = 1;
9756                }
9757              if (!bd->client.netwm.state.skip_taskbar)
9758                {
9759                   bd->client.netwm.state.skip_taskbar = 1;
9760                   bd->client.netwm.update.state = 1;
9761                }
9762           }
9763         bd->client.netwm.fetch.type = 0;
9764      }
9765    if (bd->client.icccm.fetch.machine)
9766      {
9767         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9768
9769         if ((!machine) && (bd->client.icccm.client_leader))
9770           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9771
9772         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9773         if (machine) free(machine);
9774
9775         bd->client.icccm.fetch.machine = 0;
9776         rem_change = 1;
9777      }
9778    if (bd->client.icccm.fetch.command)
9779      {
9780         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9781           {
9782              int i;
9783
9784              for (i = 0; i < bd->client.icccm.command.argc; i++)
9785                free(bd->client.icccm.command.argv[i]);
9786              free(bd->client.icccm.command.argv);
9787           }
9788         bd->client.icccm.command.argc = 0;
9789         bd->client.icccm.command.argv = NULL;
9790         ecore_x_icccm_command_get(bd->client.win,
9791                                   &(bd->client.icccm.command.argc),
9792                                   &(bd->client.icccm.command.argv));
9793         if ((bd->client.icccm.client_leader) &&
9794             (!bd->client.icccm.command.argv))
9795           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9796                                     &(bd->client.icccm.command.argc),
9797                                     &(bd->client.icccm.command.argv));
9798         bd->client.icccm.fetch.command = 0;
9799         rem_change = 1;
9800      }
9801    if (bd->client.icccm.fetch.hints)
9802      {
9803         Eina_Bool accepts_focus, is_urgent;
9804
9805         accepts_focus = EINA_TRUE;
9806         is_urgent = EINA_FALSE;
9807         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9808         if (ecore_x_icccm_hints_get(bd->client.win,
9809                                     &accepts_focus,
9810                                     &bd->client.icccm.initial_state,
9811                                     &bd->client.icccm.icon_pixmap,
9812                                     &bd->client.icccm.icon_mask,
9813                                     &bd->client.icccm.icon_window,
9814                                     &bd->client.icccm.window_group,
9815                                     &is_urgent))
9816           {
9817              bd->client.icccm.accepts_focus = accepts_focus;
9818              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9819                change_urgent = 1;
9820              bd->client.icccm.urgent = is_urgent;
9821
9822              /* If this is a new window, set the state as requested. */
9823              if ((bd->new_client) &&
9824                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9825                {
9826                   e_border_iconify(bd);
9827                   e_border_hide(bd, 1);
9828                }
9829           }
9830         bd->client.icccm.fetch.hints = 0;
9831         rem_change = 1;
9832      }
9833    if (bd->client.icccm.fetch.size_pos_hints)
9834      {
9835         Eina_Bool request_pos;
9836
9837         request_pos = EINA_FALSE;
9838         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9839                                              &request_pos,
9840                                              &bd->client.icccm.gravity,
9841                                              &bd->client.icccm.min_w,
9842                                              &bd->client.icccm.min_h,
9843                                              &bd->client.icccm.max_w,
9844                                              &bd->client.icccm.max_h,
9845                                              &bd->client.icccm.base_w,
9846                                              &bd->client.icccm.base_h,
9847                                              &bd->client.icccm.step_w,
9848                                              &bd->client.icccm.step_h,
9849                                              &bd->client.icccm.min_aspect,
9850                                              &bd->client.icccm.max_aspect))
9851           {
9852              bd->client.icccm.request_pos = request_pos;
9853           }
9854         else
9855           {
9856           }
9857         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9858         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9859         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9860         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9861         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9862         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9863         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9864         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9865         // if doing a resize, fix it up
9866         if (bd->resize_mode != RESIZE_NONE)
9867           {
9868              int x, y, w, h, new_w, new_h;
9869
9870              x = bd->x;
9871              y = bd->y;
9872              w = bd->w;
9873              h = bd->h;
9874              new_w = w;
9875              new_h = h;
9876              e_border_resize_limit(bd, &new_w, &new_h);
9877              if ((bd->resize_mode == RESIZE_TL) ||
9878                  (bd->resize_mode == RESIZE_L) ||
9879                  (bd->resize_mode == RESIZE_BL))
9880                x += (w - new_w);
9881              if ((bd->resize_mode == RESIZE_TL) ||
9882                  (bd->resize_mode == RESIZE_T) ||
9883                  (bd->resize_mode == RESIZE_TR))
9884                y += (h - new_h);
9885              e_border_move_resize(bd, x, y, new_w, new_h);
9886           }
9887         bd->client.icccm.fetch.size_pos_hints = 0;
9888         rem_change = 1;
9889      }
9890    if (bd->client.icccm.fetch.protocol)
9891      {
9892         int i, num;
9893         Ecore_X_WM_Protocol *proto;
9894
9895         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9896         if (proto)
9897           {
9898              for (i = 0; i < num; i++)
9899                {
9900                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9901                     bd->client.icccm.delete_request = 1;
9902                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9903                     bd->client.icccm.take_focus = 1;
9904                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9905                     bd->client.netwm.ping = 1;
9906                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9907                     {
9908                        bd->client.netwm.sync.request = 1;
9909                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9910                                                            &bd->client.netwm.sync.counter))
9911                          bd->client.netwm.sync.request = 0;
9912                     }
9913                }
9914              free(proto);
9915           }
9916         if (bd->client.netwm.ping)
9917           e_border_ping(bd);
9918         else
9919           {
9920              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9921              bd->ping_poller = NULL;
9922           }
9923         bd->client.icccm.fetch.protocol = 0;
9924      }
9925    if (bd->client.icccm.fetch.transient_for)
9926      {
9927         /* TODO: What do to if the transient for isn't mapped yet? */
9928         E_Border *bd_parent = NULL;
9929 #ifdef _F_DEICONIFY_APPROVE_
9930         Eina_Bool change_parent = EINA_FALSE;
9931 #endif
9932
9933         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9934         if (bd->client.icccm.transient_for)
9935           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9936         /* If we already have a parent, remove it */
9937         if (bd->parent)
9938           {
9939              if (bd_parent != bd->parent)
9940                {
9941                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9942                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9943                   bd->parent = NULL;
9944                }
9945              else
9946                bd_parent = NULL;
9947           }
9948         if ((bd_parent) && (bd_parent != bd) &&
9949             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9950           {
9951              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9952              bd->parent = bd_parent;
9953 #ifdef _F_DEICONIFY_APPROVE_
9954              change_parent = EINA_TRUE;
9955 #endif
9956           }
9957         if (bd->parent)
9958           {
9959              e_border_layer_set(bd, bd->parent->layer);
9960              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9961                {
9962                   Ecore_X_Window_Attributes attr;
9963                   bd->parent->modal = bd;
9964                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9965                   bd->parent->saved.event_mask = attr.event_mask.mine;
9966                   bd->parent->lock_close = 1;
9967                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9968                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9969                }
9970
9971              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9972                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9973                bd->take_focus = 1;
9974           }
9975
9976 #ifdef _F_DEICONIFY_APPROVE_
9977         if (change_parent)
9978           {
9979              bd->client.e.state.deiconify_approve.render_done = 0;
9980
9981              E_Border *ancestor_bd;
9982              ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
9983              if ((ancestor_bd) &&
9984                  (!e_object_is_del(E_OBJECT(ancestor_bd))))
9985                {
9986                   ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
9987                   bd->client.e.state.deiconify_approve.ancestor = NULL;
9988
9989                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
9990                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
9991                     {
9992                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
9993                          {
9994                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
9995                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
9996                             e_border_uniconify(ancestor_bd);
9997                          }
9998                     }
9999                }
10000           }
10001 #endif
10002         bd->client.icccm.fetch.transient_for = 0;
10003         rem_change = 1;
10004      }
10005    if (bd->client.icccm.fetch.window_role)
10006      {
10007         char *role = ecore_x_icccm_window_role_get(bd->client.win);
10008         eina_stringshare_replace(&bd->client.icccm.window_role, role);
10009         if (role) free(role);
10010
10011         bd->client.icccm.fetch.window_role = 0;
10012         rem_change = 1;
10013      }
10014    if (bd->client.icccm.fetch.icon_name)
10015      {
10016         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
10017         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
10018         if (icon_name) free(icon_name);
10019
10020         bd->client.icccm.fetch.icon_name = 0;
10021         rem_change = 1;
10022      }
10023    if (bd->client.netwm.fetch.icon_name)
10024      {
10025         char *icon_name;
10026         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
10027         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
10028         if (icon_name) free(icon_name);
10029
10030         bd->client.netwm.fetch.icon_name = 0;
10031         rem_change = 1;
10032      }
10033    if (bd->client.netwm.fetch.icon)
10034      {
10035         int i;
10036         if (bd->client.netwm.icons)
10037           {
10038              for (i = 0; i < bd->client.netwm.num_icons; i++)
10039                {
10040                   free(bd->client.netwm.icons[i].data);
10041                   bd->client.netwm.icons[i].data = NULL;
10042                }
10043              free(bd->client.netwm.icons);
10044           }
10045         bd->client.netwm.icons = NULL;
10046         bd->client.netwm.num_icons = 0;
10047         if (ecore_x_netwm_icons_get(bd->client.win,
10048                                      &bd->client.netwm.icons,
10049                                      &bd->client.netwm.num_icons))
10050           {
10051              // unless the rest of e17 uses border icons OTHER than icon #0
10052              // then free the rest that we don't need anymore.
10053              for (i = 1; i < bd->client.netwm.num_icons; i++)
10054                {
10055                   free(bd->client.netwm.icons[i].data);
10056                   bd->client.netwm.icons[i].data = NULL;
10057                }
10058              bd->client.netwm.num_icons = 1;
10059              bd->changes.icon = 1;
10060           }
10061         bd->client.netwm.fetch.icon = 0;
10062      }
10063    if (bd->client.netwm.fetch.user_time)
10064      {
10065         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
10066         bd->client.netwm.fetch.user_time = 0;
10067      }
10068    if (bd->client.netwm.fetch.strut)
10069      {
10070         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
10071                                              &bd->client.netwm.strut.left,
10072                                              &bd->client.netwm.strut.right,
10073                                              &bd->client.netwm.strut.top,
10074                                              &bd->client.netwm.strut.bottom,
10075                                              &bd->client.netwm.strut.left_start_y,
10076                                              &bd->client.netwm.strut.left_end_y,
10077                                              &bd->client.netwm.strut.right_start_y,
10078                                              &bd->client.netwm.strut.right_end_y,
10079                                              &bd->client.netwm.strut.top_start_x,
10080                                              &bd->client.netwm.strut.top_end_x,
10081                                              &bd->client.netwm.strut.bottom_start_x,
10082                                              &bd->client.netwm.strut.bottom_end_x))
10083           {
10084              ecore_x_netwm_strut_get(bd->client.win,
10085                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
10086                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
10087
10088              bd->client.netwm.strut.left_start_y = 0;
10089              bd->client.netwm.strut.left_end_y = 0;
10090              bd->client.netwm.strut.right_start_y = 0;
10091              bd->client.netwm.strut.right_end_y = 0;
10092              bd->client.netwm.strut.top_start_x = 0;
10093              bd->client.netwm.strut.top_end_x = 0;
10094              bd->client.netwm.strut.bottom_start_x = 0;
10095              bd->client.netwm.strut.bottom_end_x = 0;
10096           }
10097         bd->client.netwm.fetch.strut = 0;
10098      }
10099    if (bd->client.qtopia.fetch.soft_menu)
10100      {
10101         e_hints_window_qtopia_soft_menu_get(bd);
10102         bd->client.qtopia.fetch.soft_menu = 0;
10103         rem_change = 1;
10104      }
10105    if (bd->client.qtopia.fetch.soft_menus)
10106      {
10107         e_hints_window_qtopia_soft_menus_get(bd);
10108         bd->client.qtopia.fetch.soft_menus = 0;
10109         rem_change = 1;
10110      }
10111    if (bd->client.vkbd.fetch.state)
10112      {
10113         e_hints_window_virtual_keyboard_state_get(bd);
10114         bd->client.vkbd.fetch.state = 0;
10115         rem_change = 1;
10116      }
10117    if (bd->client.vkbd.fetch.vkbd)
10118      {
10119         e_hints_window_virtual_keyboard_get(bd);
10120         bd->client.vkbd.fetch.vkbd = 0;
10121         rem_change = 1;
10122      }
10123    if (bd->client.illume.conformant.fetch.conformant)
10124      {
10125         bd->client.illume.conformant.conformant =
10126           ecore_x_e_illume_conformant_get(bd->client.win);
10127         bd->client.illume.conformant.fetch.conformant = 0;
10128      }
10129    if (bd->client.illume.quickpanel.fetch.state)
10130      {
10131         bd->client.illume.quickpanel.state =
10132           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
10133         bd->client.illume.quickpanel.fetch.state = 0;
10134      }
10135    if (bd->client.illume.quickpanel.fetch.quickpanel)
10136      {
10137         bd->client.illume.quickpanel.quickpanel =
10138           ecore_x_e_illume_quickpanel_get(bd->client.win);
10139         bd->client.illume.quickpanel.fetch.quickpanel = 0;
10140      }
10141    if (bd->client.illume.quickpanel.fetch.priority.major)
10142      {
10143         bd->client.illume.quickpanel.priority.major =
10144           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
10145         bd->client.illume.quickpanel.fetch.priority.major = 0;
10146      }
10147    if (bd->client.illume.quickpanel.fetch.priority.minor)
10148      {
10149         bd->client.illume.quickpanel.priority.minor =
10150           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
10151         bd->client.illume.quickpanel.fetch.priority.minor = 0;
10152      }
10153    if (bd->client.illume.quickpanel.fetch.zone)
10154      {
10155         bd->client.illume.quickpanel.zone =
10156           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
10157         bd->client.illume.quickpanel.fetch.zone = 0;
10158      }
10159    if (bd->client.illume.drag.fetch.drag)
10160      {
10161         bd->client.illume.drag.drag =
10162           ecore_x_e_illume_drag_get(bd->client.win);
10163         bd->client.illume.drag.fetch.drag = 0;
10164      }
10165    if (bd->client.illume.drag.fetch.locked)
10166      {
10167         bd->client.illume.drag.locked =
10168           ecore_x_e_illume_drag_locked_get(bd->client.win);
10169         bd->client.illume.drag.fetch.locked = 0;
10170      }
10171    if (bd->client.illume.win_state.fetch.state)
10172      {
10173         bd->client.illume.win_state.state =
10174            ecore_x_e_illume_window_state_get(bd->client.win);
10175         bd->client.illume.win_state.fetch.state = 0;
10176 #ifdef _F_ZONE_WINDOW_ROTATION_
10177         /* E should rotate the window if the property "win_state" of window is
10178          * changed to "ECORE_X_ILLUME_WINDOW_STATE_NORMAL".
10179          * FIXME: To move below code into illume seems to better.
10180          */
10181         if (e_config->wm_win_rotation)
10182           {
10183              if (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_NORMAL)
10184                {
10185                   bd->client.e.state.rot.type = E_BORDER_ROTATION_TYPE_NORMAL;
10186                   need_rotation_set = EINA_TRUE;
10187                }
10188           }
10189 #endif
10190      }
10191    if (bd->changes.shape)
10192      {
10193         Ecore_X_Rectangle *rects;
10194         int num;
10195
10196         bd->changes.shape = 0;
10197         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
10198         if (rects)
10199           {
10200              int cw = 0, ch = 0;
10201
10202              /* This doesn't fix the race, but makes it smaller. we detect
10203               * this and if cw and ch != client w/h then mark this as needing
10204               * a shape change again to fixup next event loop.
10205               */
10206              ecore_x_window_size_get(bd->client.win, &cw, &ch);
10207              if ((cw != bd->client.w) || (ch != bd->client.h))
10208                bd->changes.shape = 1;
10209              if ((num == 1) &&
10210                  (rects[0].x == 0) &&
10211                  (rects[0].y == 0) &&
10212                  ((int)rects[0].width == cw) &&
10213                  ((int)rects[0].height == ch))
10214                {
10215                   if (bd->client.shaped)
10216                     {
10217                        bd->client.shaped = 0;
10218                        if (!bd->bordername)
10219                          bd->client.border.changed = 1;
10220                     }
10221                }
10222              else
10223                {
10224                   if (!bd->client.shaped)
10225                     {
10226                        bd->client.shaped = 1;
10227                        if (!bd->bordername)
10228                          bd->client.border.changed = 1;
10229                     }
10230                }
10231              free(rects);
10232           }
10233         else
10234           {
10235              // FIXME: no rects i think can mean... totally empty window
10236              bd->client.shaped = 0;
10237              if (!bd->bordername)
10238                bd->client.border.changed = 1;
10239           }
10240         bd->need_shape_merge = 1;
10241      }
10242    if (bd->changes.shape_input)
10243      {
10244         Ecore_X_Rectangle *rects;
10245         int num;
10246
10247         bd->changes.shape_input = 0;
10248         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
10249         if (rects)
10250           {
10251              int cw = 0, ch = 0;
10252
10253              /* This doesn't fix the race, but makes it smaller. we detect
10254               * this and if cw and ch != client w/h then mark this as needing
10255               * a shape change again to fixup next event loop.
10256               */
10257              ecore_x_window_size_get(bd->client.win, &cw, &ch);
10258              if ((cw != bd->client.w) || (ch != bd->client.h))
10259                bd->changes.shape_input = 1;
10260              if ((num == 1) &&
10261                  (rects[0].x == 0) &&
10262                  (rects[0].y == 0) &&
10263                  ((int)rects[0].width == cw) &&
10264                  ((int)rects[0].height == ch))
10265                {
10266                   if (bd->shaped_input)
10267                     {
10268                        bd->shaped_input = 0;
10269                        if (!bd->bordername)
10270                          bd->client.border.changed = 1;
10271                     }
10272                }
10273              else
10274                {
10275                   if (!bd->shaped_input)
10276                     {
10277                        bd->shaped_input = 1;
10278                        if (!bd->bordername)
10279                          bd->client.border.changed = 1;
10280                     }
10281                }
10282              free(rects);
10283           }
10284         else
10285           {
10286              bd->shaped_input = 1;
10287              if (!bd->bordername)
10288                bd->client.border.changed = 1;
10289           }
10290         bd->need_shape_merge = 1;
10291      }
10292    if (bd->client.mwm.fetch.hints)
10293      {
10294         int pb;
10295
10296         bd->client.mwm.exists =
10297           ecore_x_mwm_hints_get(bd->client.win,
10298                                 &bd->client.mwm.func,
10299                                 &bd->client.mwm.decor,
10300                                 &bd->client.mwm.input);
10301         pb = bd->client.mwm.borderless;
10302         bd->client.mwm.borderless = 0;
10303         if (bd->client.mwm.exists)
10304           {
10305              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
10306                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
10307                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
10308                bd->client.mwm.borderless = 1;
10309           }
10310         if (bd->client.mwm.borderless != pb)
10311           {
10312              if ((!bd->lock_border) || (!bd->client.border.name))
10313                bd->client.border.changed = 1;
10314           }
10315         bd->client.mwm.fetch.hints = 0;
10316         rem_change = 1;
10317      }
10318    if (bd->client.e.fetch.video_parent)
10319      {
10320         /* unlinking child/parent */
10321         if (bd->client.e.state.video_parent_border != NULL)
10322           {
10323              bd->client.e.state.video_parent_border->client.e.state.video_child =
10324                eina_list_remove
10325                (bd->client.e.state.video_parent_border->client.e.state.video_child,
10326                    bd);
10327           }
10328
10329         ecore_x_window_prop_card32_get(bd->client.win,
10330                                        ECORE_X_ATOM_E_VIDEO_PARENT,
10331                                        &bd->client.e.state.video_parent,
10332                                        1);
10333
10334         /* linking child/parent */
10335         if (bd->client.e.state.video_parent != 0)
10336           {
10337              E_Border *tmp;
10338              Eina_List *l;
10339
10340              EINA_LIST_FOREACH(borders, l, tmp)
10341                if (tmp->client.win == bd->client.e.state.video_parent)
10342                  {
10343                     /* fprintf(stderr, "child added to parent \\o/\n"); */
10344                     bd->client.e.state.video_parent_border = tmp;
10345                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
10346                                                                        bd);
10347                     if (bd->desk != tmp->desk)
10348                       e_border_desk_set(bd, tmp->desk);
10349                     break;
10350                  }
10351           }
10352
10353         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
10354
10355         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
10356         rem_change = 1;
10357      }
10358    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
10359      {
10360         unsigned int xy[2];
10361
10362         ecore_x_window_prop_card32_get(bd->client.win,
10363                                        ECORE_X_ATOM_E_VIDEO_POSITION,
10364                                        xy,
10365                                        2);
10366         bd->client.e.state.video_position.x = xy[0];
10367         bd->client.e.state.video_position.y = xy[1];
10368         bd->client.e.state.video_position.updated = 1;
10369         bd->client.e.fetch.video_position = 0;
10370         bd->x = bd->client.e.state.video_position.x;
10371         bd->y = bd->client.e.state.video_position.y;
10372
10373         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
10374      }
10375    if (bd->client.netwm.update.state)
10376      {
10377         e_hints_window_state_set(bd);
10378         /* Some stats might change the border, like modal */
10379         if (((!bd->lock_border) || (!bd->client.border.name)) &&
10380             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10381           {
10382              bd->client.border.changed = 1;
10383           }
10384         if (bd->parent)
10385           {
10386              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10387                {
10388                   bd->parent->modal = bd;
10389                   if (bd->parent->focused)
10390                     e_border_focus_set(bd, 1, 1);
10391                }
10392           }
10393         else if (bd->leader)
10394           {
10395              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10396                {
10397                   bd->leader->modal = bd;
10398                   if (bd->leader->focused)
10399                     e_border_focus_set(bd, 1, 1);
10400                   else
10401                     {
10402                        Eina_List *l;
10403                        E_Border *child;
10404
10405                        EINA_LIST_FOREACH(bd->leader->group, l, child)
10406                          {
10407                             if ((child != bd) && (child->focused))
10408                               e_border_focus_set(bd, 1, 1);
10409                          }
10410                     }
10411                }
10412           }
10413         bd->client.netwm.update.state = 0;
10414      }
10415
10416    if (bd->new_client)
10417      {
10418         E_Event_Border_Add *ev;
10419         E_Exec_Instance *inst;
10420
10421         ev = E_NEW(E_Event_Border_Add, 1);
10422         ev->border = bd;
10423         e_object_ref(E_OBJECT(bd));
10424         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
10425         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
10426
10427         if ((!bd->lock_border) || (!bd->client.border.name))
10428           bd->client.border.changed = 1;
10429
10430           {
10431              char *str = NULL;
10432
10433              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
10434                  ((bd->client.icccm.client_leader > 0) &&
10435                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
10436                 )
10437                {
10438                   if (!strncmp(str, "E_START|", 8))
10439                     {
10440                        int id;
10441
10442                        id = atoi(str + 8);
10443                        if (id > 0) bd->client.netwm.startup_id = id;
10444                     }
10445                   free(str);
10446                }
10447           }
10448         /* It's ok not to have fetch flag, should only be set on startup
10449          *     * and not changed. */
10450         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
10451           {
10452              if (bd->client.icccm.client_leader)
10453                {
10454                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
10455                     bd->client.netwm.pid = -1;
10456                }
10457              else
10458                bd->client.netwm.pid = -1;
10459           }
10460
10461         if (!bd->re_manage)
10462           {
10463              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
10464                                                         bd->client.netwm.pid);
10465              if ((inst) && (inst->used == 0))
10466                {
10467                   E_Zone *zone;
10468                   E_Desk *desk;
10469
10470                   inst->used++;
10471                   zone = e_container_zone_number_get(bd->zone->container,
10472                                                      inst->screen);
10473                   if (zone) e_border_zone_set(bd, zone);
10474                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
10475                                           inst->desk_y);
10476                   if (desk) e_border_desk_set(bd, desk);
10477                   e_exec_instance_found(inst);
10478                }
10479
10480              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
10481                {
10482                   E_Border *bdl = NULL;
10483
10484                   bdl = bd->parent;
10485                   if (!bdl)
10486                     {
10487                        if (bd->leader) bdl = bd->leader;
10488                     }
10489                   if (!bdl)
10490                     {
10491                        E_Border *child;
10492                        E_Border_List *bl;
10493
10494                        bl = e_container_border_list_first(bd->zone->container);
10495                        while ((child = e_container_border_list_next(bl)))
10496                          {
10497                             if (child == bd) continue;
10498                             if (e_object_is_del(E_OBJECT(child))) continue;
10499                             if ((bd->client.icccm.client_leader) &&
10500                                 (child->client.icccm.client_leader ==
10501                                     bd->client.icccm.client_leader))
10502                               {
10503                                  bdl = child;
10504                                  break;
10505                               }
10506                          }
10507                        e_container_border_list_free(bl);
10508                     }
10509                   if (bdl)
10510                     {
10511                        if (bdl->zone)
10512                          e_border_zone_set(bd, bdl->zone);
10513                        if (bdl->desk)
10514                          e_border_desk_set(bd, bdl->desk);
10515                        else
10516                          e_border_stick(bd);
10517                     }
10518                }
10519           }
10520      }
10521
10522 #ifdef _F_USE_DESK_WINDOW_PROFILE_
10523    if (need_desk_set)
10524      {
10525         E_Container *con = bd->zone->container;
10526         E_Desk *desk = NULL;
10527         Eina_List *l;
10528         const char *str;
10529         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
10530           {
10531              desk = e_container_desk_window_profile_get(con, str);
10532              if (desk)
10533                {
10534                   if (bd->desk != desk)
10535                     {
10536                        bd->client.e.state.profile = eina_stringshare_add(str);
10537                        if (bd->zone != desk->zone)
10538                          e_border_zone_set(bd, desk->zone);
10539                        e_border_desk_set(bd, desk);
10540                     }
10541                   break;
10542                }
10543           }
10544      }
10545 #endif
10546
10547    /* PRE_POST_FETCH calls e_remember apply for new client */
10548    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
10549    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
10550    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
10551
10552 #ifdef _F_ZONE_WINDOW_ROTATION_
10553    if (e_config->wm_win_rotation)
10554      {
10555         if ((need_rotation_set) &&
10556             (bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_NORMAL))
10557           {
10558              Eina_Bool hint = EINA_FALSE;
10559              int ang = 0;
10560              int x, y, w, h, move;
10561
10562              ELB(ELBT_ROT, "NEED ROT", bd->client.win);
10563              bd->client.e.state.rot.changes = _e_border_rotation_angle_get(bd);
10564
10565              if (bd->client.e.state.rot.changes == -1)
10566                {
10567                   ang = bd->client.e.state.rot.curr;
10568
10569                   hint = _e_border_rotation_geom_get(bd, bd->zone, ang, &x, &y, &w, &h, &move);
10570                   if (hint)
10571                     {
10572                        _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
10573                        ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
10574                             bd->client.icccm.name, x, y, w, h);
10575                     }
10576                }
10577              else bd->changed = 1;
10578           }
10579      }
10580 #endif
10581
10582    if (bd->need_reparent)
10583      {
10584         if (!bd->internal)
10585           ecore_x_window_save_set_add(bd->client.win);
10586         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
10587         if (bd->visible)
10588           {
10589              if ((bd->new_client) && (bd->internal) &&
10590                  (bd->internal_ecore_evas))
10591                ecore_evas_show(bd->internal_ecore_evas);
10592              ecore_x_window_show(bd->client.win);
10593           }
10594         bd->need_reparent = 0;
10595      }
10596
10597    if ((bd->client.border.changed) && (!bd->shaded) &&
10598        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10599      {
10600         const char *bordername;
10601
10602         if (bd->fullscreen)
10603           bordername = "borderless";
10604         else if (bd->bordername)
10605           bordername = bd->bordername;
10606         else if ((bd->client.mwm.borderless) || (bd->borderless))
10607           bordername = "borderless";
10608         else if (((bd->client.icccm.transient_for != 0) ||
10609                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
10610                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10611                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10612           bordername = "noresize_dialog";
10613         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10614                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10615           bordername = "noresize";
10616         else if (bd->client.shaped)
10617           bordername = "shaped";
10618         else if ((!bd->client.icccm.accepts_focus) &&
10619                  (!bd->client.icccm.take_focus))
10620           bordername = "nofocus";
10621         else if (bd->client.icccm.urgent)
10622           bordername = "urgent";
10623         else if ((bd->client.icccm.transient_for != 0) ||
10624                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10625           bordername = "dialog";
10626         else if (bd->client.netwm.state.modal)
10627           bordername = "modal";
10628         else if ((bd->client.netwm.state.skip_taskbar) ||
10629                  (bd->client.netwm.state.skip_pager))
10630           bordername = "skipped";
10631         else if ((bd->internal) && (bd->client.icccm.class) &&
10632                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
10633           bordername = "internal_fileman";
10634         else
10635           bordername = e_config->theme_default_border_style;
10636         if (!bordername) bordername = "default";
10637
10638         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
10639           {
10640              Evas_Object *o;
10641              char buf[4096];
10642              int ok;
10643
10644              bd->changes.border = 1;
10645              eina_stringshare_replace(&bd->client.border.name, bordername);
10646
10647              if (bd->bg_object)
10648                {
10649                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
10650                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
10651                   bd->changes.size = 1;
10652                   evas_object_del(bd->bg_object);
10653                }
10654              o = edje_object_add(bd->bg_evas);
10655              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
10656              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10657              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
10658                {
10659                   if (bd->client.border.name != e_config->theme_default_border_style)
10660                     {
10661                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
10662                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10663                     }
10664                   if (!ok)
10665                     {
10666                        ok = e_theme_edje_object_set(o, "base/theme/borders",
10667                                                     "e/widgets/border/default/border");
10668                        if (ok)
10669                          {
10670                             /* Reset default border style to default */
10671                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
10672                             e_config_save_queue();
10673                          }
10674                     }
10675                }
10676
10677              bd->shaped = 0;
10678              if (ok)
10679                {
10680                   const char *shape_option, *argb_option;
10681                   int use_argb = 0;
10682
10683                   bd->bg_object = o;
10684
10685                   if ((e_config->use_composite) && (!bd->client.argb))
10686                     {
10687                        argb_option = edje_object_data_get(o, "argb");
10688                        if ((argb_option) && (!strcmp(argb_option, "1")))
10689                          use_argb = 1;
10690
10691                        if (use_argb != bd->argb)
10692                          _e_border_frame_replace(bd, use_argb);
10693
10694                        o = bd->bg_object;
10695                     }
10696
10697                   if (!bd->argb)
10698                     {
10699                        shape_option = edje_object_data_get(o, "shaped");
10700                        if ((shape_option) && (!strcmp(shape_option, "1")))
10701                          bd->shaped = 1;
10702                     }
10703
10704                   if (bd->client.netwm.name)
10705                     edje_object_part_text_set(o, "e.text.title",
10706                                               bd->client.netwm.name);
10707                   else if (bd->client.icccm.title)
10708                     edje_object_part_text_set(o, "e.text.title",
10709                                               bd->client.icccm.title);
10710                }
10711              else
10712                {
10713                   evas_object_del(o);
10714                   bd->bg_object = NULL;
10715                }
10716
10717              _e_border_client_inset_calc(bd);
10718
10719              bd->w += (bd->client_inset.l + bd->client_inset.r);
10720              bd->h += (bd->client_inset.t + bd->client_inset.b);
10721              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
10722              bd->changes.size = 1;
10723              /*  really needed ? */
10724              ecore_x_window_move(bd->client.shell_win,
10725                                  bd->client_inset.l,
10726                                  bd->client_inset.t);
10727
10728              if (bd->maximized != E_MAXIMIZE_NONE)
10729                {
10730                   E_Maximize maximized = bd->maximized;
10731
10732                   /* to force possible resizes */
10733                   bd->maximized = E_MAXIMIZE_NONE;
10734
10735                   _e_border_maximize(bd, maximized);
10736
10737                   /* restore maximized state */
10738                   bd->maximized = maximized;
10739
10740                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
10741                                                bd->maximized & E_MAXIMIZE_VERTICAL);
10742                }
10743              if (bd->bg_object)
10744                {
10745                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
10746                                                   _e_border_cb_signal_bind, bd);
10747                   if (bd->focused)
10748                     {
10749                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
10750                        if (bd->icon_object)
10751                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10752                     }
10753                   if (bd->shaded)
10754                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
10755                   if (bd->sticky)
10756                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
10757                   if (bd->hung)
10758                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
10759                   // FIXME: in eval -do differently
10760                   //         edje_object_message_signal_process(bd->bg_object);
10761                   //         e_border_frame_recalc(bd);
10762
10763                   evas_object_move(bd->bg_object, 0, 0);
10764                   evas_object_resize(bd->bg_object, bd->w, bd->h);
10765                   evas_object_show(bd->bg_object);
10766                }
10767           }
10768         bd->client.border.changed = 0;
10769
10770         if (bd->icon_object)
10771           {
10772              if (bd->bg_object)
10773                {
10774                   evas_object_show(bd->icon_object);
10775                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10776                }
10777              else
10778                evas_object_hide(bd->icon_object);
10779           }
10780      }
10781
10782    if (rem_change) e_remember_update(bd);
10783
10784    if (change_urgent)
10785      {
10786         E_Event_Border_Urgent_Change *ev;
10787
10788         if (bd->client.icccm.urgent)
10789           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
10790         else
10791           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
10792
10793         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
10794         ev->border = bd;
10795         e_object_ref(E_OBJECT(bd));
10796         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
10797                         _e_border_event_border_urgent_change_free, NULL);
10798      }
10799
10800    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10801 }
10802
10803 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10804 static void
10805 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10806 {
10807    E_Border* temp_bd = NULL;
10808    E_Border* top_focusable_bd = NULL;
10809    Eina_Bool is_fully_obscured = EINA_FALSE;
10810    Ecore_X_XRegion *visible_region = NULL;
10811    Ecore_X_XRegion *win_region = NULL;
10812    Ecore_X_Rectangle visible_rect, win_rect;
10813    E_Border_List *bl;
10814
10815    // set the entire visible region as a root geometry
10816    visible_rect.x = bd->zone->x;
10817    visible_rect.y = bd->zone->y;
10818    visible_rect.width = bd->zone->w;
10819    visible_rect.height = bd->zone->h;
10820
10821    visible_region = ecore_x_xregion_new();
10822    if (!visible_region) return;
10823
10824    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10825
10826    bl = e_container_border_list_last(bd->zone->container);
10827    while ((temp_bd = e_container_border_list_prev(bl)))
10828      {
10829         if (temp_bd == bd) break;
10830
10831         if (temp_bd == focused) continue;
10832         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10833         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10834         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10835             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10836             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10837             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10838             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10839             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10840             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10841           {
10842              if (!top_focusable_bd)
10843                {
10844                   top_focusable_bd = temp_bd;
10845                }
10846
10847              win_rect.x = temp_bd->x;
10848              win_rect.y = temp_bd->y;
10849              win_rect.width = temp_bd->w;
10850              win_rect.height = temp_bd->h;
10851
10852              // if it stick out or is bigger than the entire visible region,
10853              // clip it by the entire visible's geometry.
10854              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10855                                   win_rect.width, win_rect.height,
10856                                   visible_rect.x, visible_rect.y,
10857                                   (int)(visible_rect.width), (int)(visible_rect.height));
10858
10859              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10860                {
10861                   win_region = ecore_x_xregion_new();
10862                   if (win_region)
10863                     {
10864                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10865                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10866                        ecore_x_xregion_free(win_region);
10867                        win_region = NULL;
10868
10869                        if (ecore_x_xregion_is_empty(visible_region))
10870                          {
10871                             is_fully_obscured = EINA_TRUE;
10872                             break;
10873                          }
10874                     }
10875                }
10876           }
10877      }
10878
10879    if (is_fully_obscured == EINA_TRUE)
10880      {
10881         e_border_focus_set(top_focusable_bd, 1, 1);
10882      }
10883    else
10884      {
10885         e_border_focus_set(bd, 1, 1);
10886      }
10887
10888    if (visible_region) ecore_x_xregion_free(visible_region);
10889    e_container_border_list_free(bl);
10890 }
10891
10892 static void
10893 _e_border_latest_stacked_focus(E_Border *bd)
10894 {
10895    E_Border *temp_bd;
10896    int root_w, root_h;
10897
10898    root_w = bd->zone->w;
10899    root_h = bd->zone->h;
10900
10901    Eina_List *l;
10902    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10903      {
10904         if (bd == temp_bd) continue;
10905         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10906         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10907
10908         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10909             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10910             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10911             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10912             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10913             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10914             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10915           {
10916              _e_border_latest_stacked_focus_check_set(temp_bd);
10917              break;
10918           }
10919      }
10920 }
10921
10922 static void
10923 _e_border_check_stack (E_Border *bd)
10924 {
10925    E_Border* temp_bd = NULL;
10926    E_Border* top_bd = NULL;
10927    int passed_focus = 0;
10928    int passed = 0;
10929    int root_w = bd->zone->w;
10930    int root_h = bd->zone->h;
10931
10932    E_Border_List *bl;
10933    bl = e_container_border_list_last(bd->zone->container);
10934    while ((temp_bd = e_container_border_list_prev(bl)))
10935      {
10936         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10937         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10938         if ((temp_bd != bd) &&
10939             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10940
10941         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10942            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10943            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10944            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10945            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10946            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10947            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10948           {
10949              if (bd == temp_bd)
10950                {
10951                   if (!passed)
10952                     {
10953                        e_border_focus_set_with_pointer(bd);
10954                        break;
10955                     }
10956                   else
10957                     {
10958                        if (!passed_focus)
10959                          {
10960                             e_border_focus_set_with_pointer(top_bd);
10961                          }
10962                        break;
10963                     }
10964                }
10965              else
10966                {
10967                   if (!passed)
10968                     {
10969                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10970                          {
10971                             if (!bd->lock_focus_out)
10972                               {
10973                                  e_border_focus_latest_set(bd);
10974                               }
10975                          }
10976                     }
10977                }
10978
10979              if (!passed)
10980                {
10981                   passed = 1;
10982                   top_bd = temp_bd;
10983                }
10984
10985              if (temp_bd == focused)
10986                {
10987                   passed_focus = 1;
10988                }
10989           }
10990      }
10991    e_container_border_list_free(bl);
10992 }
10993
10994 static void
10995 _e_border_focus_top_stack_set(E_Border* bd)
10996 {
10997    E_Border *temp_bd;
10998    int root_w, root_h;
10999
11000    root_w = bd->zone->w;
11001    root_h = bd->zone->h;
11002
11003    E_Border_List *bl;
11004    bl = e_container_border_list_last(bd->zone->container);
11005    while ((temp_bd = e_container_border_list_prev(bl)))
11006      {
11007         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
11008         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
11009         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
11010
11011         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
11012            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
11013            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
11014            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
11015            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
11016            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
11017            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
11018           {
11019              if (!temp_bd->focused)
11020                {
11021                   /* this border is the top of the latest stack */
11022                   e_border_focus_set (temp_bd, 1, 1);
11023                }
11024              break;
11025           }
11026      }
11027    e_container_border_list_free(bl);
11028 }
11029 #endif
11030
11031 static void
11032 _e_border_eval(E_Border *bd)
11033 {
11034    E_Event_Border_Property *event;
11035    E_Border_Pending_Move_Resize *pnd;
11036    int rem_change = 0;
11037    int send_event = 1;
11038
11039    if (e_object_is_del(E_OBJECT(bd)))
11040      {
11041         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
11042         bd->changed = 0;
11043         return;
11044      }
11045
11046    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
11047
11048    if (bd->new_client)
11049      {
11050         int zx = 0, zy = 0, zw = 0, zh = 0;
11051
11052         if (bd->zone)
11053           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
11054
11055         /*
11056          * Limit maximum size of windows to useful geometry
11057          */
11058         // TODO: temoporary limited maximize algorithm
11059         // ->
11060         /*if (bd->w > zw)
11061           rw = zw;
11062           else
11063           rw = bd->w;
11064
11065           if (bd->h > zh)
11066           rh = zh;
11067           else
11068           rh = bd->h;
11069
11070           if ((rw != bd->w) || (rh != bd->h))
11071           {
11072           bd->w = rw;
11073           bd->h = rh;
11074           e_border_resize (bd, bd->w, bd->h);
11075           }*/
11076         // <-
11077
11078         if (bd->re_manage)
11079           {
11080              bd->x -= bd->client_inset.l;
11081              bd->y -= bd->client_inset.t;
11082              bd->changes.pos = 1;
11083              bd->placed = 1;
11084           }
11085         else if ((!bd->placed) && (bd->client.icccm.request_pos))
11086           {
11087
11088              Ecore_X_Window_Attributes *att;
11089              int bw;
11090
11091              att = &bd->client.initial_attributes;
11092              bw = att->border * 2;
11093              switch (bd->client.icccm.gravity)
11094                {
11095                 case ECORE_X_GRAVITY_N:
11096                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
11097                    bd->y = att->y;
11098                    break;
11099
11100                 case ECORE_X_GRAVITY_NE:
11101                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
11102                    bd->y = att->y;
11103                    break;
11104
11105                 case ECORE_X_GRAVITY_E:
11106                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
11107                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
11108                    break;
11109
11110                 case ECORE_X_GRAVITY_SE:
11111                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
11112                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
11113                    break;
11114
11115                 case ECORE_X_GRAVITY_S:
11116                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
11117                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
11118                    break;
11119
11120                 case ECORE_X_GRAVITY_SW:
11121                    bd->x = att->x;
11122                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
11123                    break;
11124
11125                 case ECORE_X_GRAVITY_W:
11126                    bd->x = att->x;
11127                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
11128                    break;
11129
11130                 case ECORE_X_GRAVITY_CENTER:
11131                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
11132                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
11133                    break;
11134
11135                 case ECORE_X_GRAVITY_NW:
11136                 default:
11137                    bd->x = att->x;
11138                    bd->y = att->y;
11139                }
11140
11141              /*
11142               * This ensures that windows that like to open with a x/y
11143               * position smaller than returned by e_zone_useful_geometry_get()
11144               * are moved to useful positions.
11145               */
11146              // ->
11147              if (e_config->geometry_auto_move)
11148                {
11149                   if (bd->x < zx)
11150                     bd->x = zx;
11151
11152                   if (bd->y < zy)
11153                     bd->y = zy;
11154
11155                   if (bd->x + bd->w > zx + zw)
11156                     bd->x = zx + zw - bd->w;
11157
11158                   if (bd->y + bd->h > zy + zh)
11159                     bd->y = zy + zh - bd->h;
11160                   // <--
11161
11162                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
11163                     {
11164                        bd->changes.pos = 1;
11165                        bd->placed = 1;
11166                     }
11167                }
11168              else
11169                {
11170                   bd->changes.pos = 1;
11171                   bd->placed = 1;
11172                }
11173           }
11174         if (!bd->placed)
11175           {
11176              /* FIXME: special placement for dialogs etc. etc. etc goes
11177               * here */
11178              /* FIXME: what if parent is not on this desktop - or zone? */
11179              if ((bd->parent) && (bd->parent->visible))
11180                {
11181                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
11182                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
11183                   bd->changes.pos = 1;
11184                   bd->placed = 1;
11185                }
11186 #if 0
11187              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
11188                {
11189                   /* TODO: Place in center of group */
11190                }
11191 #endif
11192              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11193                {
11194                   bd->x = zx + ((zw - bd->w) / 2);
11195                   bd->y = zy + ((zh - bd->h) / 2);
11196                   bd->changes.pos = 1;
11197                   bd->placed = 1;
11198                }
11199           }
11200         if (!bd->placed)
11201           {
11202              Eina_List *skiplist = NULL;
11203              int new_x, new_y;
11204
11205              if (zw > bd->w)
11206                new_x = zx + (rand() % (zw - bd->w));
11207              else
11208                new_x = zx;
11209              if (zh > bd->h)
11210                new_y = zy + (rand() % (zh - bd->h));
11211              else
11212                new_y = zy;
11213
11214              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
11215                {
11216                   skiplist = eina_list_append(skiplist, bd);
11217                   if (bd->desk)
11218                     e_place_desk_region_smart(bd->desk, skiplist,
11219                                               bd->x, bd->y, bd->w, bd->h,
11220                                               &new_x, &new_y);
11221                   else
11222                     e_place_zone_region_smart(bd->zone, skiplist,
11223                                               bd->x, bd->y, bd->w, bd->h,
11224                                               &new_x, &new_y);
11225                   eina_list_free(skiplist);
11226                }
11227              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
11228                {
11229                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
11230                                       &new_x, &new_y);
11231                }
11232              else
11233                {
11234                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
11235                                       bd->client_inset.t, &new_x, &new_y);
11236                }
11237              bd->x = new_x;
11238              bd->y = new_y;
11239              bd->changes.pos = 1;
11240           }
11241
11242         EINA_LIST_FREE(bd->pending_move_resize, pnd)
11243           {
11244              if ((!bd->lock_client_location) && (pnd->move))
11245                {
11246                   bd->x = pnd->x;
11247                   bd->y = pnd->y;
11248                   bd->changes.pos = 1;
11249                   bd->placed = 1;
11250                   if (pnd->without_border)
11251                     {
11252                        bd->x -= bd->client_inset.l;
11253                        bd->y -= bd->client_inset.t;
11254                     }
11255                }
11256              if ((!bd->lock_client_size) && (pnd->resize))
11257                {
11258                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
11259                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
11260                   bd->client.w = pnd->w;
11261                   bd->client.h = pnd->h;
11262                   bd->changes.size = 1;
11263                }
11264
11265              free(pnd);
11266           }
11267
11268         /* Recreate state */
11269         e_hints_window_init(bd);
11270         if ((bd->client.e.state.centered) &&
11271             ((!bd->remember) ||
11272              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
11273           {
11274              bd->x = zx + (zw - bd->w) / 2;
11275              bd->y = zy + (zh - bd->h) / 2;
11276              bd->changes.pos = 1;
11277              bd->placed = 1;
11278           }
11279
11280         _e_border_client_move_resize_send(bd);
11281
11282         /* if the explicit geometry request asks for the app to be
11283          * in another zone - well move it there */
11284         {
11285            E_Zone *zone;
11286
11287            zone = e_container_zone_at_point_get(bd->zone->container,
11288                                                 bd->x + (bd->w / 2),
11289                                                 bd->y + (bd->h / 2));
11290            if (!zone)
11291              zone = e_container_zone_at_point_get(bd->zone->container,
11292                                                   bd->x,
11293                                                   bd->y);
11294            if (!zone)
11295              zone = e_container_zone_at_point_get(bd->zone->container,
11296                                                   bd->x + bd->w - 1,
11297                                                   bd->y);
11298            if (!zone)
11299              zone = e_container_zone_at_point_get(bd->zone->container,
11300                                                   bd->x + bd->w - 1,
11301                                                   bd->y + bd->h - 1);
11302            if (!zone)
11303              zone = e_container_zone_at_point_get(bd->zone->container,
11304                                                   bd->x,
11305                                                   bd->y + bd->h - 1);
11306            if ((zone) && (zone != bd->zone))
11307              e_border_zone_set(bd, zone);
11308         }
11309      }
11310
11311    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
11312
11313    /* effect changes to the window border itself */
11314    if ((bd->changes.shading))
11315      {
11316         /*  show at start of unshade (but don't hide until end of shade) */
11317         if (bd->shaded)
11318           ecore_x_window_raise(bd->client.shell_win);
11319         bd->changes.shading = 0;
11320         rem_change = 1;
11321      }
11322    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
11323      {
11324         if (bd->shaded)
11325           ecore_x_window_lower(bd->client.shell_win);
11326         else
11327           ecore_x_window_raise(bd->client.shell_win);
11328         bd->changes.shaded = 0;
11329         rem_change = 1;
11330      }
11331    else if ((bd->changes.shaded) && (bd->changes.pos))
11332      {
11333         if (bd->shaded)
11334           ecore_x_window_lower(bd->client.shell_win);
11335         else
11336           ecore_x_window_raise(bd->client.shell_win);
11337         bd->changes.size = 1;
11338         bd->changes.shaded = 0;
11339         rem_change = 1;
11340      }
11341    else if ((bd->changes.shaded) && (bd->changes.size))
11342      {
11343         if (bd->shaded)
11344           ecore_x_window_lower(bd->client.shell_win);
11345         else
11346           ecore_x_window_raise(bd->client.shell_win);
11347         bd->changes.shaded = 0;
11348         rem_change = 1;
11349      }
11350    else if (bd->changes.shaded)
11351      {
11352         if (bd->shaded)
11353           ecore_x_window_lower(bd->client.shell_win);
11354         else
11355           ecore_x_window_raise(bd->client.shell_win);
11356         bd->changes.size = 1;
11357         bd->changes.shaded = 0;
11358         rem_change = 1;
11359      }
11360
11361    if (bd->changes.size)
11362      {
11363         int x = 0, y = 0, xx = 0, yy = 0;
11364
11365         if ((bd->shaded) && (!bd->shading))
11366           {
11367              evas_obscured_clear(bd->bg_evas);
11368           }
11369         else
11370           {
11371              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
11372              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
11373
11374              evas_obscured_clear(bd->bg_evas);
11375              evas_obscured_rectangle_add(bd->bg_evas,
11376                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
11377
11378              if (bd->shading)
11379                {
11380                   if (bd->shade.dir == E_DIRECTION_UP)
11381                     {
11382                        y = yy - bd->client.h;
11383                     }
11384                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11385                     {
11386                        x = xx - bd->client.w;
11387                     }
11388                }
11389           }
11390
11391         if (bd->client.e.state.video)
11392           {
11393              if (bd->client.e.state.video_position.updated)
11394                {
11395                   ecore_x_window_move(bd->win,
11396                                       bd->client.e.state.video_parent_border->x +
11397                                       bd->client.e.state.video_parent_border->client_inset.l +
11398                                       bd->client.e.state.video_parent_border->fx.x +
11399                                       bd->client.e.state.video_position.x,
11400                                       bd->client.e.state.video_parent_border->y +
11401                                       bd->client.e.state.video_parent_border->client_inset.t +
11402                                       bd->client.e.state.video_parent_border->fx.y +
11403                                       bd->client.e.state.video_position.y);
11404                   bd->client.e.state.video_position.updated = 0;
11405                }
11406           }
11407         else if (!bd->changes.pos)
11408           {
11409              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11410              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11411              bd->post_resize = 1;
11412           }
11413         else
11414           {
11415              E_Border *tmp;
11416              Eina_List *l;
11417
11418              ecore_x_window_move_resize(bd->win,
11419                                         bd->x + bd->fx.x,
11420                                         bd->y + bd->fx.y,
11421                                         bd->w, bd->h);
11422
11423              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
11424                ecore_x_window_move(tmp->win,
11425                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
11426                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
11427           }
11428
11429         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
11430
11431         if ((!bd->shaded) || (bd->shading))
11432           ecore_x_window_move_resize(bd->client.shell_win,
11433                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
11434
11435         if (bd->internal_ecore_evas)
11436           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
11437         else if (!bd->client.e.state.video)
11438           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
11439
11440         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
11441         evas_object_resize(bd->bg_object, bd->w, bd->h);
11442         e_container_shape_resize(bd->shape, bd->w, bd->h);
11443         if (bd->changes.pos)
11444           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11445
11446         _e_border_client_move_resize_send(bd);
11447
11448         bd->changes.pos = 0;
11449         bd->changes.size = 0;
11450         rem_change = 1;
11451      }
11452    else if (bd->changes.pos)
11453      {
11454         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11455         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11456         bd->post_move = 1;
11457
11458         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11459
11460         _e_border_client_move_resize_send(bd);
11461
11462         bd->changes.pos = 0;
11463         rem_change = 1;
11464      }
11465
11466    if (bd->changes.reset_gravity)
11467      {
11468         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
11469         bd->changes.reset_gravity = 0;
11470         rem_change = 1;
11471      }
11472
11473    if (bd->need_shape_merge)
11474      {
11475         _e_border_shape_input_rectangle_set(bd);
11476         if ((bd->shaped) || (bd->client.shaped))
11477           {
11478              Ecore_X_Window twin, twin2;
11479              int x, y;
11480
11481              twin = ecore_x_window_override_new
11482                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
11483              if (bd->shaped)
11484                ecore_x_window_shape_window_set(twin, bd->bg_win);
11485              else
11486                {
11487                   Ecore_X_Rectangle rects[4];
11488
11489                   rects[0].x = 0;
11490                   rects[0].y = 0;
11491                   rects[0].width = bd->w;
11492                   rects[0].height = bd->client_inset.t;
11493                   rects[1].x = 0;
11494                   rects[1].y = bd->client_inset.t;
11495                   rects[1].width = bd->client_inset.l;
11496                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11497                   rects[2].x = bd->w - bd->client_inset.r;
11498                   rects[2].y = bd->client_inset.t;
11499                   rects[2].width = bd->client_inset.r;
11500                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11501                   rects[3].x = 0;
11502                   rects[3].y = bd->h - bd->client_inset.b;
11503                   rects[3].width = bd->w;
11504                   rects[3].height = bd->client_inset.b;
11505                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
11506                }
11507              twin2 = ecore_x_window_override_new
11508                (bd->zone->container->scratch_win, 0, 0,
11509                 bd->w - bd->client_inset.l - bd->client_inset.r,
11510                 bd->h - bd->client_inset.t - bd->client_inset.b);
11511              x = 0;
11512              y = 0;
11513              if ((bd->shading) || (bd->shaded))
11514                {
11515                   if (bd->shade.dir == E_DIRECTION_UP)
11516                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
11517                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11518                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
11519                }
11520              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
11521                                                 x, y);
11522              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
11523                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
11524                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
11525              ecore_x_window_shape_window_add_xy(twin, twin2,
11526                                                 bd->client_inset.l,
11527                                                 bd->client_inset.t);
11528              ecore_x_window_free(twin2);
11529              ecore_x_window_shape_window_set(bd->win, twin);
11530              ecore_x_window_free(twin);
11531           }
11532         else
11533           ecore_x_window_shape_mask_set(bd->win, 0);
11534         //      bd->need_shape_export = 1;
11535         bd->need_shape_merge = 0;
11536      }
11537
11538    if (bd->need_shape_export)
11539      {
11540         Ecore_X_Rectangle *rects, *orects;
11541         int num;
11542
11543         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
11544         if (rects)
11545           {
11546              int changed;
11547
11548              changed = 1;
11549              if ((num == bd->shape_rects_num) && (bd->shape_rects))
11550                {
11551                   int i;
11552
11553                   orects = bd->shape_rects;
11554                   changed = 0;
11555                   for (i = 0; i < num; i++)
11556                     {
11557                        if (rects[i].x < 0)
11558                          {
11559                             rects[i].width -= rects[i].x;
11560                             rects[i].x = 0;
11561                          }
11562                        if ((rects[i].x + (int)rects[i].width) > bd->w)
11563                          rects[i].width = rects[i].width - rects[i].x;
11564                        if (rects[i].y < 0)
11565                          {
11566                             rects[i].height -= rects[i].y;
11567                             rects[i].y = 0;
11568                          }
11569                        if ((rects[i].y + (int)rects[i].height) > bd->h)
11570                          rects[i].height = rects[i].height - rects[i].y;
11571
11572                        if ((orects[i].x != rects[i].x) ||
11573                            (orects[i].y != rects[i].y) ||
11574                            (orects[i].width != rects[i].width) ||
11575                            (orects[i].height != rects[i].height))
11576                          {
11577                             changed = 1;
11578                             break;
11579                          }
11580                     }
11581                }
11582              if (changed)
11583                {
11584                   if (bd->client.shaped)
11585                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
11586                   else
11587                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
11588                   E_FREE(bd->shape_rects);
11589                   bd->shape_rects = rects;
11590                   bd->shape_rects_num = num;
11591                   e_container_shape_rects_set(bd->shape, rects, num);
11592                }
11593              else
11594                free(rects);
11595           }
11596         else
11597           {
11598              E_FREE(bd->shape_rects);
11599              bd->shape_rects = NULL;
11600              bd->shape_rects_num = 0;
11601              e_container_shape_rects_set(bd->shape, NULL, 0);
11602           }
11603         bd->need_shape_export = 0;
11604      }
11605
11606    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
11607      {
11608         int x, y;
11609
11610         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
11611         if ((!bd->placed) && (!bd->re_manage) &&
11612             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
11613             (!((bd->client.icccm.transient_for != 0) ||
11614                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
11615             (!bdmove) && (!bdresize))
11616           {
11617              /* Set this window into moving state */
11618
11619              bd->cur_mouse_action = e_action_find("window_move");
11620              if (bd->cur_mouse_action)
11621                {
11622                   if ((!bd->cur_mouse_action->func.end_mouse) &&
11623                       (!bd->cur_mouse_action->func.end))
11624                     bd->cur_mouse_action = NULL;
11625                   if (bd->cur_mouse_action)
11626                     {
11627                        bd->x = x - (bd->w >> 1);
11628                        bd->y = y - (bd->client_inset.t >> 1);
11629                        bd->changed = 1;
11630                        bd->changes.pos = 1;
11631
11632                        _e_border_client_move_resize_send(bd);
11633                     }
11634                }
11635           }
11636
11637         _e_border_show(bd);
11638
11639         if (bd->cur_mouse_action)
11640           {
11641              bd->moveinfo.down.x = bd->x + bd->fx.x;
11642              bd->moveinfo.down.y = bd->y + bd->fx.y;
11643              bd->moveinfo.down.w = bd->w;
11644              bd->moveinfo.down.h = bd->h;
11645              bd->mouse.current.mx = x;
11646              bd->mouse.current.my = y;
11647              bd->moveinfo.down.button = 0;
11648              bd->moveinfo.down.mx = x;
11649              bd->moveinfo.down.my = y;
11650
11651              grabbed = 1;
11652              e_object_ref(E_OBJECT(bd->cur_mouse_action));
11653              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
11654              if (e_config->border_raise_on_mouse_action)
11655                e_border_raise(bd);
11656              e_border_focus_set(bd, 1, 1);
11657           }
11658         bd->changes.visible = 0;
11659         rem_change = 1;
11660      }
11661
11662    if (bd->changes.icon)
11663      {
11664         if (bd->desktop)
11665           {
11666              efreet_desktop_free(bd->desktop);
11667              bd->desktop = NULL;
11668           }
11669         if (bd->icon_object)
11670           {
11671              evas_object_del(bd->icon_object);
11672              bd->icon_object = NULL;
11673           }
11674         if (bd->remember && bd->remember->prop.desktop_file)
11675           {
11676              const char *desktop = bd->remember->prop.desktop_file;
11677
11678              bd->desktop = efreet_desktop_get(desktop);
11679              if (!bd->desktop)
11680                bd->desktop = efreet_util_desktop_name_find(desktop);
11681           }
11682         if (!bd->desktop)
11683           {
11684              if ((bd->client.icccm.name) && (bd->client.icccm.class))
11685                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
11686                                                                bd->client.icccm.class);
11687           }
11688         if (!bd->desktop)
11689           {
11690              /* libreoffice and maybe others match window class
11691                 with .desktop file name */
11692              if (bd->client.icccm.class)
11693                {
11694                   char buf[128];
11695                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
11696                   bd->desktop = efreet_util_desktop_file_id_find(buf);
11697                }
11698           }
11699         if (!bd->desktop)
11700           {
11701              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
11702                                                       bd->client.netwm.pid);
11703              if (bd->desktop) efreet_desktop_ref(bd->desktop);
11704           }
11705         if (!bd->desktop && bd->client.icccm.name)
11706           {
11707              /* this works for most cases as fallback. useful when app is
11708                 run from a shell  */
11709              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
11710           }
11711         if (!bd->desktop && bd->client.icccm.transient_for)
11712           {
11713              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
11714              if (bd2 && bd2->desktop)
11715                {
11716                   efreet_desktop_ref(bd2->desktop);
11717                   bd->desktop = bd2->desktop;
11718                }
11719           }
11720         if (bd->desktop)
11721           {
11722              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
11723                                             bd->desktop->orig_path);
11724           }
11725
11726         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
11727         if ((bd->focused) && (bd->icon_object))
11728           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
11729         if (bd->bg_object)
11730           {
11731              evas_object_show(bd->icon_object);
11732              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
11733           }
11734         else
11735           evas_object_hide(bd->icon_object);
11736
11737         {
11738            E_Event_Border_Icon_Change *ev;
11739
11740            ev = E_NEW(E_Event_Border_Icon_Change, 1);
11741            ev->border = bd;
11742            e_object_ref(E_OBJECT(bd));
11743            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
11744            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
11745                            _e_border_event_border_icon_change_free, NULL);
11746         }
11747         bd->changes.icon = 0;
11748      }
11749
11750    bd->new_client = 0;
11751    bd->changed = 0;
11752    bd->changes.stack = 0;
11753    bd->changes.prop = 0;
11754
11755 #ifdef _F_ZONE_WINDOW_ROTATION_
11756    if (bd->client.e.state.rot.changes != -1)
11757      {
11758         e_border_rotation_set(bd, bd->client.e.state.rot.changes);
11759         bd->client.e.state.rot.changes = -1;
11760      }
11761 #endif
11762
11763    if ((bd->take_focus) || (bd->want_focus))
11764      {
11765         bd->take_focus = 0;
11766 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11767         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
11768             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
11769             (bd->want_focus))
11770 #else // original
11771         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
11772 #endif
11773           {
11774              bd->want_focus = 0;
11775 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11776              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
11777                 _e_border_check_stack(bd);
11778              else
11779 #endif
11780              e_border_focus_set_with_pointer(bd);
11781           }
11782         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11783           {
11784              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
11785                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
11786                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
11787                    e_border_focused_get())))
11788                {
11789                   e_border_focus_set_with_pointer(bd);
11790                }
11791           }
11792         else
11793           {
11794              /* focus window by default when it is the only one on desk */
11795              E_Border *bd2 = NULL;
11796              Eina_List *l;
11797              EINA_LIST_FOREACH(focus_stack, l, bd2)
11798                {
11799                   if (bd == bd2) continue;
11800                   if ((!bd2->iconic) && (bd2->visible) &&
11801                       ((bd->desk == bd2->desk) || bd2->sticky))
11802                     break;
11803                }
11804
11805              if (!bd2)
11806                {
11807                   e_border_focus_set_with_pointer(bd);
11808                }
11809           }
11810      }
11811
11812    if (bd->need_maximize)
11813      {
11814         E_Maximize max;
11815         max = bd->maximized;
11816         bd->maximized = E_MAXIMIZE_NONE;
11817         e_border_maximize(bd, max);
11818         bd->need_maximize = 0;
11819      }
11820
11821    if (bd->need_fullscreen)
11822      {
11823         e_border_fullscreen(bd, e_config->fullscreen_policy);
11824         bd->need_fullscreen = 0;
11825      }
11826
11827    if (rem_change)
11828      e_remember_update(bd);
11829
11830    if (send_event) // FIXME: send only if a property changed - above need to
11831      { // check on that. for now - always send.
11832         event = E_NEW(E_Event_Border_Property, 1);
11833         event->border = bd;
11834         e_object_ref(E_OBJECT(bd));
11835         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11836      }
11837    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11838 }
11839
11840 static void
11841 _e_border_moveinfo_gather(E_Border   *bd,
11842                           const char *source)
11843 {
11844    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11845    else if (e_util_glob_match(source, "mouse,*,2"))
11846      bd->moveinfo.down.button = 2;
11847    else if (e_util_glob_match(source, "mouse,*,3"))
11848      bd->moveinfo.down.button = 3;
11849    else bd->moveinfo.down.button = 0;
11850    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11851      {
11852         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11853         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11854      }
11855    else
11856      {
11857         bd->moveinfo.down.mx = bd->mouse.current.mx;
11858         bd->moveinfo.down.my = bd->mouse.current.my;
11859      }
11860 }
11861
11862 static void
11863 _e_border_resize_handle(E_Border *bd)
11864 {
11865    int x, y, w, h;
11866    int new_x, new_y, new_w, new_h;
11867    int tw, th;
11868    Eina_List *skiplist = NULL;
11869
11870    x = bd->x;
11871    y = bd->y;
11872    w = bd->w;
11873    h = bd->h;
11874
11875    if ((bd->resize_mode == RESIZE_TR) ||
11876        (bd->resize_mode == RESIZE_R) ||
11877        (bd->resize_mode == RESIZE_BR))
11878      {
11879         if ((bd->moveinfo.down.button >= 1) &&
11880             (bd->moveinfo.down.button <= 3))
11881           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11882             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11883         else
11884           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11885      }
11886    else if ((bd->resize_mode == RESIZE_TL) ||
11887             (bd->resize_mode == RESIZE_L) ||
11888             (bd->resize_mode == RESIZE_BL))
11889      {
11890         if ((bd->moveinfo.down.button >= 1) &&
11891             (bd->moveinfo.down.button <= 3))
11892           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11893             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11894         else
11895           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11896      }
11897
11898    if ((bd->resize_mode == RESIZE_TL) ||
11899        (bd->resize_mode == RESIZE_T) ||
11900        (bd->resize_mode == RESIZE_TR))
11901      {
11902         if ((bd->moveinfo.down.button >= 1) &&
11903             (bd->moveinfo.down.button <= 3))
11904           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11905             (bd->mouse.current.my - bd->moveinfo.down.my);
11906         else
11907           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11908      }
11909    else if ((bd->resize_mode == RESIZE_BL) ||
11910             (bd->resize_mode == RESIZE_B) ||
11911             (bd->resize_mode == RESIZE_BR))
11912      {
11913         if ((bd->moveinfo.down.button >= 1) &&
11914             (bd->moveinfo.down.button <= 3))
11915           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11916             (bd->mouse.current.my - bd->moveinfo.down.my);
11917         else
11918           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11919      }
11920
11921    tw = bd->w;
11922    th = bd->h;
11923
11924    if ((bd->resize_mode == RESIZE_TL) ||
11925        (bd->resize_mode == RESIZE_L) ||
11926        (bd->resize_mode == RESIZE_BL))
11927      x += (tw - w);
11928    if ((bd->resize_mode == RESIZE_TL) ||
11929        (bd->resize_mode == RESIZE_T) ||
11930        (bd->resize_mode == RESIZE_TR))
11931      y += (th - h);
11932
11933    skiplist = eina_list_append(skiplist, bd);
11934    e_resist_container_border_position(bd->zone->container, skiplist,
11935                                       bd->x, bd->y, bd->w, bd->h,
11936                                       x, y, w, h,
11937                                       &new_x, &new_y, &new_w, &new_h);
11938    eina_list_free(skiplist);
11939
11940    w = new_w;
11941    h = new_h;
11942    e_border_resize_limit(bd, &new_w, &new_h);
11943    if ((bd->resize_mode == RESIZE_TL) ||
11944        (bd->resize_mode == RESIZE_L) ||
11945        (bd->resize_mode == RESIZE_BL))
11946      new_x += (w - new_w);
11947    if ((bd->resize_mode == RESIZE_TL) ||
11948        (bd->resize_mode == RESIZE_T) ||
11949        (bd->resize_mode == RESIZE_TR))
11950      new_y += (h - new_h);
11951
11952    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11953 }
11954
11955 static Eina_Bool
11956 _e_border_shade_animator(void *data)
11957 {
11958    E_Border *bd = data;
11959    double dt, val;
11960    double dur = bd->client.h / e_config->border_shade_speed;
11961
11962    dt = ecore_loop_time_get() - bd->shade.start;
11963    val = dt / dur;
11964
11965    if (val < 0.0) val = 0.0;
11966    else if (val > 1.0) val = 1.0;
11967
11968    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11969      {
11970         bd->shade.val =
11971            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
11972         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11973      }
11974    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
11975      {
11976         bd->shade.val =
11977            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
11978         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11979      }
11980    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
11981      {
11982         bd->shade.val =
11983            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
11984         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11985      }
11986    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
11987      {
11988         bd->shade.val =
11989            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11990         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11991      }
11992    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
11993      {
11994         bd->shade.val =
11995            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
11996         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11997      }
11998    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
11999      {
12000         bd->shade.val =
12001            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
12002         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
12003      }
12004    else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
12005      {
12006         bd->shade.val =
12007            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.0);
12008         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
12009      }
12010    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE)
12011      {
12012         bd->shade.val =
12013            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
12014         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
12015      }
12016    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
12017      {
12018         bd->shade.val =
12019            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
12020         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
12021      }
12022    else
12023      {
12024         bd->shade.val =
12025            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
12026         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
12027      }
12028
12029    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
12030    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
12031    else if (bd->shade.val > .999)
12032      bd->shade.val = 1.0;
12033
12034    if (bd->shade.dir == E_DIRECTION_UP)
12035      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
12036    else if (bd->shade.dir == E_DIRECTION_DOWN)
12037      {
12038         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
12039         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
12040         bd->changes.pos = 1;
12041      }
12042    else if (bd->shade.dir == E_DIRECTION_LEFT)
12043      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
12044    else if (bd->shade.dir == E_DIRECTION_RIGHT)
12045      {
12046         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
12047         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
12048         bd->changes.pos = 1;
12049      }
12050
12051    if ((bd->shaped) || (bd->client.shaped))
12052      {
12053         bd->need_shape_merge = 1;
12054         bd->need_shape_export = 1;
12055      }
12056    if (bd->shaped_input)
12057      {
12058         bd->need_shape_merge = 1;
12059      }
12060    bd->changes.size = 1;
12061    bd->changed = 1;
12062
12063    /* we're done */
12064    if (val == 1)
12065      {
12066         E_Event_Border_Resize *ev;
12067
12068         bd->shading = 0;
12069         bd->shaded = !(bd->shaded);
12070         bd->changes.size = 1;
12071         bd->changes.shaded = 1;
12072         bd->changes.shading = 1;
12073         bd->changed = 1;
12074         bd->shade.anim = NULL;
12075
12076         if (bd->shaded)
12077           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
12078         else
12079           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
12080         edje_object_message_signal_process(bd->bg_object);
12081         e_border_frame_recalc(bd);
12082
12083         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
12084         ev = E_NEW(E_Event_Border_Resize, 1);
12085         ev->border = bd;
12086         e_object_ref(E_OBJECT(bd));
12087 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
12088         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
12089         return ECORE_CALLBACK_CANCEL;
12090      }
12091    return ECORE_CALLBACK_RENEW;
12092 }
12093
12094 static void
12095 _e_border_event_border_resize_free(void *data __UNUSED__,
12096                                    void      *ev)
12097 {
12098    E_Event_Border_Resize *e;
12099
12100    e = ev;
12101 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
12102    e_object_unref(E_OBJECT(e->border));
12103    E_FREE(e);
12104 }
12105
12106 static void
12107 _e_border_event_border_move_free(void *data __UNUSED__,
12108                                  void      *ev)
12109 {
12110    E_Event_Border_Move *e;
12111
12112    e = ev;
12113 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
12114    e_object_unref(E_OBJECT(e->border));
12115    E_FREE(e);
12116 }
12117
12118 static void
12119 _e_border_event_border_add_free(void *data __UNUSED__,
12120                                 void      *ev)
12121 {
12122    E_Event_Border_Add *e;
12123
12124    e = ev;
12125 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
12126    e_object_unref(E_OBJECT(e->border));
12127    E_FREE(e);
12128 }
12129
12130 static void
12131 _e_border_event_border_remove_free(void *data __UNUSED__,
12132                                    void      *ev)
12133 {
12134    E_Event_Border_Remove *e;
12135
12136    e = ev;
12137 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
12138    e_object_unref(E_OBJECT(e->border));
12139    E_FREE(e);
12140 }
12141
12142 static void
12143 _e_border_event_border_show_free(void *data __UNUSED__,
12144                                  void      *ev)
12145 {
12146    E_Event_Border_Show *e;
12147
12148    e = ev;
12149 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
12150    e_object_unref(E_OBJECT(e->border));
12151    E_FREE(e);
12152 }
12153
12154 static void
12155 _e_border_event_border_hide_free(void *data __UNUSED__,
12156                                  void      *ev)
12157 {
12158    E_Event_Border_Hide *e;
12159
12160    e = ev;
12161 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
12162    e_object_unref(E_OBJECT(e->border));
12163    E_FREE(e);
12164 }
12165
12166 static void
12167 _e_border_event_border_iconify_free(void *data __UNUSED__,
12168                                     void      *ev)
12169 {
12170    E_Event_Border_Iconify *e;
12171
12172    e = ev;
12173 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
12174    e_object_unref(E_OBJECT(e->border));
12175    E_FREE(e);
12176 }
12177
12178 static void
12179 _e_border_event_border_uniconify_free(void *data __UNUSED__,
12180                                       void      *ev)
12181 {
12182    E_Event_Border_Uniconify *e;
12183
12184    e = ev;
12185 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
12186    e_object_unref(E_OBJECT(e->border));
12187    E_FREE(e);
12188 }
12189
12190 static void
12191 _e_border_event_border_stick_free(void *data __UNUSED__,
12192                                   void      *ev)
12193 {
12194    E_Event_Border_Stick *e;
12195
12196    e = ev;
12197 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
12198    e_object_unref(E_OBJECT(e->border));
12199    E_FREE(e);
12200 }
12201
12202 static void
12203 _e_border_event_border_unstick_free(void *data __UNUSED__,
12204                                     void      *ev)
12205 {
12206    E_Event_Border_Unstick *e;
12207
12208    e = ev;
12209 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
12210    e_object_unref(E_OBJECT(e->border));
12211    E_FREE(e);
12212 }
12213
12214 static void
12215 _e_border_event_border_zone_set_free(void *data __UNUSED__,
12216                                      void      *ev)
12217 {
12218    E_Event_Border_Zone_Set *e;
12219
12220    e = ev;
12221 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
12222    e_object_unref(E_OBJECT(e->border));
12223    e_object_unref(E_OBJECT(e->zone));
12224    E_FREE(e);
12225 }
12226
12227 static void
12228 _e_border_event_border_desk_set_free(void *data __UNUSED__,
12229                                      void      *ev)
12230 {
12231    E_Event_Border_Desk_Set *e;
12232
12233    e = ev;
12234 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
12235    e_object_unref(E_OBJECT(e->border));
12236    e_object_unref(E_OBJECT(e->desk));
12237    E_FREE(e);
12238 }
12239
12240 static void
12241 _e_border_event_border_stack_free(void *data __UNUSED__,
12242                                   void      *ev)
12243 {
12244    E_Event_Border_Stack *e;
12245
12246    e = ev;
12247 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
12248    e_object_unref(E_OBJECT(e->border));
12249    if (e->stack)
12250      {
12251 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
12252           e_object_unref(E_OBJECT(e->stack));
12253      }
12254    E_FREE(e);
12255 }
12256
12257 static void
12258 _e_border_event_border_icon_change_free(void *data __UNUSED__,
12259                                         void      *ev)
12260 {
12261    E_Event_Border_Icon_Change *e;
12262
12263    e = ev;
12264 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
12265    e_object_unref(E_OBJECT(e->border));
12266    E_FREE(e);
12267 }
12268
12269 static void
12270 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
12271                                           void      *ev)
12272 {
12273    E_Event_Border_Urgent_Change *e;
12274
12275    e = ev;
12276    e_object_unref(E_OBJECT(e->border));
12277    E_FREE(e);
12278 }
12279
12280 static void
12281 _e_border_event_border_focus_in_free(void *data __UNUSED__,
12282                                      void      *ev)
12283 {
12284    E_Event_Border_Focus_In *e;
12285
12286    e = ev;
12287    e_object_unref(E_OBJECT(e->border));
12288    E_FREE(e);
12289 }
12290
12291 static void
12292 _e_border_event_border_focus_out_free(void *data __UNUSED__,
12293                                       void      *ev)
12294 {
12295    E_Event_Border_Focus_Out *e;
12296
12297    e = ev;
12298    e_object_unref(E_OBJECT(e->border));
12299    E_FREE(e);
12300 }
12301
12302 static void
12303 _e_border_event_border_property_free(void *data __UNUSED__,
12304                                      void      *ev)
12305 {
12306    E_Event_Border_Property *e;
12307
12308    e = ev;
12309    e_object_unref(E_OBJECT(e->border));
12310    E_FREE(e);
12311 }
12312
12313 static void
12314 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
12315                                        void      *ev)
12316 {
12317    E_Event_Border_Fullscreen *e;
12318
12319    e = ev;
12320 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
12321    e_object_unref(E_OBJECT(e->border));
12322    E_FREE(e);
12323 }
12324
12325 static void
12326 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
12327                                          void      *ev)
12328 {
12329    E_Event_Border_Unfullscreen *e;
12330
12331    e = ev;
12332 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
12333    e_object_unref(E_OBJECT(e->border));
12334    E_FREE(e);
12335 }
12336
12337 #ifdef _F_ZONE_WINDOW_ROTATION_
12338 static void
12339 _e_border_event_border_rotation_change_begin_free(void *data __UNUSED__,
12340                                                   void      *ev)
12341 {
12342    E_Event_Border_Rotation_Change_Begin *e;
12343    e = ev;
12344    e_object_unref(E_OBJECT(e->border));
12345    E_FREE(e);
12346 }
12347
12348 static void
12349 _e_border_event_border_rotation_change_cancel_free(void *data __UNUSED__,
12350                                                    void      *ev)
12351 {
12352    E_Event_Border_Rotation_Change_Cancel *e;
12353    e = ev;
12354    e_object_unref(E_OBJECT(e->border));
12355    E_FREE(e);
12356 }
12357
12358 static void
12359 _e_border_event_border_rotation_change_end_free(void *data __UNUSED__,
12360                                                 void      *ev)
12361 {
12362    E_Event_Border_Rotation_Change_End *e;
12363    e = ev;
12364    e_object_unref(E_OBJECT(e->border));
12365    E_FREE(e);
12366 }
12367
12368 static void
12369 _e_border_event_border_rotation_change_begin_send(E_Border *bd)
12370 {
12371    E_Event_Border_Rotation_Change_Begin *ev = NULL;
12372    ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
12373    if (ev)
12374      {
12375         ev->border = bd;
12376         e_object_ref(E_OBJECT(bd));
12377         ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_BEGIN,
12378                         ev,
12379                         _e_border_event_border_rotation_change_begin_free,
12380                         NULL);
12381      }
12382 }
12383 #endif
12384
12385 static void
12386 _e_border_zone_update(E_Border *bd)
12387 {
12388    E_Container *con;
12389    Eina_List *l;
12390    E_Zone *zone;
12391
12392    /* still within old zone - leave it there */
12393    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12394                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
12395 #if _F_BORDER_CLIP_TO_ZONE_
12396      {
12397         _e_border_shape_input_clip_to_zone(bd);
12398         return;
12399      }
12400 #else
12401      return;
12402 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12403    /* find a new zone */
12404    con = bd->zone->container;
12405    EINA_LIST_FOREACH(con->zones, l, zone)
12406      {
12407         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12408                          zone->x, zone->y, zone->w, zone->h))
12409           {
12410              e_border_zone_set(bd, zone);
12411 #if _F_BORDER_CLIP_TO_ZONE_
12412              _e_border_shape_input_clip_to_zone(bd);
12413 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12414              return;
12415           }
12416      }
12417 }
12418
12419 static int
12420 _e_border_resize_begin(E_Border *bd)
12421 {
12422    int ret;
12423
12424    if (!bd->lock_user_stacking)
12425      {
12426         if (e_config->border_raise_on_mouse_action)
12427           e_border_raise(bd);
12428      }
12429    if ((bd->shaded) || (bd->shading) ||
12430        (bd->fullscreen) || (bd->lock_user_size))
12431      return 0;
12432
12433    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12434      ret = e_grabinput_get(bd->win, 0, bd->win);
12435    else
12436      ret = e_grabinput_get(bd->win, 0, 0);
12437
12438    if (grabbed && !ret)
12439      {
12440         grabbed = 0;
12441         return 0;
12442      }
12443
12444    if (bd->client.netwm.sync.request)
12445      {
12446         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12447         bd->client.netwm.sync.serial = 1;
12448         bd->client.netwm.sync.wait = 0;
12449         bd->client.netwm.sync.send_time = ecore_loop_time_get();
12450      }
12451
12452    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
12453
12454    bdresize = bd;
12455    return 1;
12456 }
12457
12458 static int
12459 _e_border_resize_end(E_Border *bd)
12460 {
12461    if (grabbed)
12462      {
12463         e_grabinput_release(bd->win, bd->win);
12464         grabbed = 0;
12465      }
12466    if (bd->client.netwm.sync.alarm)
12467      {
12468         E_Border_Pending_Move_Resize *pnd;
12469
12470         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12471         bd->client.netwm.sync.alarm = 0;
12472         /* resize to last geometry if sync alarm for it was not yet handled */
12473         if (bd->pending_move_resize)
12474           {
12475              bd->changed = 1;
12476              bd->changes.pos = 1;
12477              bd->changes.size = 1;
12478              _e_border_client_move_resize_send(bd);
12479           }
12480
12481         EINA_LIST_FREE(bd->pending_move_resize, pnd)
12482           E_FREE(pnd);
12483      }
12484
12485    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
12486
12487    bdresize = NULL;
12488
12489    /* If this border was maximized, we need to unset Maximized state or
12490     * on restart, E still thinks it's maximized */
12491    if (bd->maximized != E_MAXIMIZE_NONE)
12492      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
12493                                   bd->maximized & E_MAXIMIZE_NONE);
12494    return 1;
12495 }
12496
12497 static void
12498 _e_border_resize_update(E_Border *bd)
12499 {
12500    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
12501 }
12502
12503 static int
12504 _e_border_move_begin(E_Border *bd)
12505 {
12506    int ret;
12507    if (!bd->lock_user_stacking)
12508      {
12509         if (e_config->border_raise_on_mouse_action)
12510           e_border_raise(bd);
12511      }
12512    if ((bd->fullscreen) || (bd->lock_user_location))
12513      return 0;
12514
12515    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12516      ret = e_grabinput_get(bd->win, 0, bd->win);
12517    else
12518      ret = e_grabinput_get(bd->win, 0, 0);
12519
12520    if (grabbed && !ret)
12521      {
12522         grabbed = 0;
12523         return 0;
12524      }
12525 #if 0
12526    if (bd->client.netwm.sync.request)
12527      {
12528         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12529         bd->client.netwm.sync.serial = 0;
12530         bd->client.netwm.sync.wait = 0;
12531         bd->client.netwm.sync.time = ecore_loop_time_get();
12532      }
12533 #endif
12534    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
12535
12536    bdmove = bd;
12537    return 1;
12538 }
12539
12540 static int
12541 _e_border_move_end(E_Border *bd)
12542 {
12543    if (grabbed)
12544      {
12545         e_grabinput_release(bd->win, bd->win);
12546         grabbed = 0;
12547      }
12548 #if 0
12549    if (bd->client.netwm.sync.alarm)
12550      {
12551         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12552         bd->client.netwm.sync.alarm = 0;
12553      }
12554 #endif
12555    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
12556
12557    bdmove = NULL;
12558    return 1;
12559 }
12560
12561 static void
12562 _e_border_move_update(E_Border *bd)
12563 {
12564    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
12565 }
12566
12567 static Eina_Bool
12568 _e_border_cb_ping_poller(void *data)
12569 {
12570    E_Border *bd;
12571
12572    bd = data;
12573    if (bd->ping_ok)
12574      {
12575         if (bd->hung)
12576           {
12577              bd->hung = 0;
12578              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
12579              if (bd->kill_timer)
12580                {
12581                   ecore_timer_del(bd->kill_timer);
12582                   bd->kill_timer = NULL;
12583                }
12584           }
12585      }
12586    else
12587      {
12588         /* if time between last ping and now is greater
12589          * than half the ping interval... */
12590         if ((ecore_loop_time_get() - bd->ping) >
12591             ((e_config->ping_clients_interval *
12592               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
12593           {
12594              if (!bd->hung)
12595                {
12596                   bd->hung = 1;
12597                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
12598                   /* FIXME: if below dialog is up - hide it now */
12599                }
12600              if (bd->delete_requested)
12601                {
12602                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
12603                   e_border_act_kill_begin(bd);
12604                }
12605           }
12606      }
12607    bd->ping_poller = NULL;
12608    e_border_ping(bd);
12609    return ECORE_CALLBACK_CANCEL;
12610 }
12611
12612 static Eina_Bool
12613 _e_border_cb_kill_timer(void *data)
12614 {
12615    E_Border *bd;
12616
12617    bd = data;
12618 // dont wait until it's hung -
12619 //   if (bd->hung)
12620 //     {
12621         if (bd->client.netwm.pid > 1)
12622           kill(bd->client.netwm.pid, SIGKILL);
12623 //     }
12624    bd->kill_timer = NULL;
12625    return ECORE_CALLBACK_CANCEL;
12626 }
12627
12628 static void
12629 _e_border_pointer_resize_begin(E_Border *bd)
12630 {
12631    switch (bd->resize_mode)
12632      {
12633       case RESIZE_TL:
12634         e_pointer_type_push(bd->pointer, bd, "resize_tl");
12635         break;
12636
12637       case RESIZE_T:
12638         e_pointer_type_push(bd->pointer, bd, "resize_t");
12639         break;
12640
12641       case RESIZE_TR:
12642         e_pointer_type_push(bd->pointer, bd, "resize_tr");
12643         break;
12644
12645       case RESIZE_R:
12646         e_pointer_type_push(bd->pointer, bd, "resize_r");
12647         break;
12648
12649       case RESIZE_BR:
12650         e_pointer_type_push(bd->pointer, bd, "resize_br");
12651         break;
12652
12653       case RESIZE_B:
12654         e_pointer_type_push(bd->pointer, bd, "resize_b");
12655         break;
12656
12657       case RESIZE_BL:
12658         e_pointer_type_push(bd->pointer, bd, "resize_bl");
12659         break;
12660
12661       case RESIZE_L:
12662         e_pointer_type_push(bd->pointer, bd, "resize_l");
12663         break;
12664      }
12665 }
12666
12667 static void
12668 _e_border_pointer_resize_end(E_Border *bd)
12669 {
12670    switch (bd->resize_mode)
12671      {
12672       case RESIZE_TL:
12673         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
12674         break;
12675
12676       case RESIZE_T:
12677         e_pointer_type_pop(bd->pointer, bd, "resize_t");
12678         break;
12679
12680       case RESIZE_TR:
12681         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
12682         break;
12683
12684       case RESIZE_R:
12685         e_pointer_type_pop(bd->pointer, bd, "resize_r");
12686         break;
12687
12688       case RESIZE_BR:
12689         e_pointer_type_pop(bd->pointer, bd, "resize_br");
12690         break;
12691
12692       case RESIZE_B:
12693         e_pointer_type_pop(bd->pointer, bd, "resize_b");
12694         break;
12695
12696       case RESIZE_BL:
12697         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
12698         break;
12699
12700       case RESIZE_L:
12701         e_pointer_type_pop(bd->pointer, bd, "resize_l");
12702         break;
12703      }
12704 }
12705
12706 static void
12707 _e_border_pointer_move_begin(E_Border *bd)
12708 {
12709    e_pointer_type_push(bd->pointer, bd, "move");
12710 }
12711
12712 static void
12713 _e_border_pointer_move_end(E_Border *bd)
12714 {
12715    e_pointer_type_pop(bd->pointer, bd, "move");
12716 }
12717
12718 static Eina_List *_e_border_hooks = NULL;
12719 static int _e_border_hooks_delete = 0;
12720 static int _e_border_hooks_walking = 0;
12721
12722 static void
12723 _e_border_hooks_clean(void)
12724 {
12725    Eina_List *l, *ln;
12726    E_Border_Hook *bh;
12727
12728    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
12729      {
12730         if (bh->delete_me)
12731           {
12732              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
12733              free(bh);
12734           }
12735      }
12736 }
12737
12738 static void
12739 _e_border_hook_call(E_Border_Hook_Point hookpoint,
12740                     void               *bd)
12741 {
12742    Eina_List *l;
12743    E_Border_Hook *bh;
12744
12745    _e_border_hooks_walking++;
12746    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
12747      {
12748         if (bh->delete_me) continue;
12749         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
12750      }
12751    _e_border_hooks_walking--;
12752    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
12753      _e_border_hooks_clean();
12754 }
12755
12756 EAPI E_Border_Hook *
12757 e_border_hook_add(E_Border_Hook_Point               hookpoint,
12758                   void                              (*func)(void *data,
12759                                               void *bd),
12760                   void                             *data)
12761 {
12762    E_Border_Hook *bh;
12763
12764    bh = E_NEW(E_Border_Hook, 1);
12765    if (!bh) return NULL;
12766    bh->hookpoint = hookpoint;
12767    bh->func = func;
12768    bh->data = data;
12769    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
12770    return bh;
12771 }
12772
12773 EAPI void
12774 e_border_hook_del(E_Border_Hook *bh)
12775 {
12776    bh->delete_me = 1;
12777    if (_e_border_hooks_walking == 0)
12778      {
12779         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
12780         free(bh);
12781      }
12782    else
12783      _e_border_hooks_delete++;
12784 }
12785
12786 EAPI void
12787 e_border_focus_track_freeze(void)
12788 {
12789    focus_track_frozen++;
12790 }
12791
12792 EAPI void
12793 e_border_focus_track_thaw(void)
12794 {
12795    focus_track_frozen--;
12796 }
12797
12798 EAPI E_Border *
12799 e_border_under_pointer_get(E_Desk   *desk,
12800                            E_Border *exclude)
12801 {
12802    E_Border *bd = NULL, *cbd;
12803    Eina_List *l;
12804    int x, y;
12805
12806    /* We need to ensure that we can get the container window for the
12807     * zone of either the given desk or the desk of the excluded
12808     * window, so return if neither is given */
12809    if (desk)
12810      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
12811    else if (exclude)
12812      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
12813    else
12814      return NULL;
12815
12816    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
12817      {
12818         if (!cbd) continue;
12819         /* If a border was specified which should be excluded from the list
12820          * (because it will be closed shortly for example), skip */
12821         if ((exclude) && (cbd == exclude)) continue;
12822         if ((desk) && (cbd->desk != desk)) continue;
12823         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
12824           continue;
12825         /* If the layer is higher, the position of the window is higher
12826          * (always on top vs always below) */
12827         if (!bd || (cbd->layer > bd->layer))
12828           {
12829              bd = cbd;
12830              break;
12831           }
12832      }
12833    return bd;
12834 }
12835
12836 static Eina_Bool
12837 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
12838 {
12839    if (warp_to)
12840      {
12841         int x, y;
12842         double spd;
12843
12844         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
12845         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
12846             (y - warp_y) > 5 || (y - warp_y) < -5)
12847           {
12848              /* User moved the mouse, so stop warping */
12849              warp_to = 0;
12850              goto cleanup;
12851           }
12852
12853         /* We just use the same warp speed as configured
12854          * for the windowlist */
12855         spd = e_config->winlist_warp_speed;
12856         x = warp_x;
12857         y = warp_y;
12858         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12859         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12860         if (warp_x == x && warp_y == y)
12861           {
12862              warp_x = warp_to_x;
12863              warp_y = warp_to_y;
12864              warp_to = 0;
12865              goto cleanup;
12866           }
12867         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12868         return ECORE_CALLBACK_RENEW;
12869      }
12870  cleanup:
12871    ecore_timer_del(warp_timer);
12872    warp_timer = NULL;
12873    return ECORE_CALLBACK_CANCEL;
12874 }
12875
12876 EAPI int
12877 e_border_pointer_warp_to_center(E_Border *bd)
12878 {
12879    int x, y;
12880
12881    /* Do not slide pointer when disabled (probably breaks focus
12882     * on sloppy/mouse focus but requested by users). */
12883    if (!e_config->pointer_slide) return 0;
12884    /* Only warp the pointer if it is not already in the area of
12885     * the given border */
12886    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12887    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12888        (y >= bd->y) && (y <= (bd->y + bd->h)))
12889      return 0;
12890
12891    warp_to_x = bd->x + (bd->w / 2);
12892    if (warp_to_x < (bd->zone->x + 1))
12893      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12894    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12895      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12896
12897    warp_to_y = bd->y + (bd->h / 2);
12898    if (warp_to_y < (bd->zone->y + 1))
12899      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12900    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12901      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12902
12903    warp_to = 1;
12904    warp_to_win = bd->zone->container->win;
12905    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12906    if (!warp_timer)
12907      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12908    return 1;
12909 }
12910
12911 EAPI void
12912 e_border_comp_hidden_set(E_Border *bd,
12913                          Eina_Bool hidden)
12914 {
12915    E_Border *tmp;
12916    Eina_List *l;
12917
12918    E_OBJECT_CHECK(bd);
12919    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12920
12921    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12922      {
12923        if (hidden)
12924          ecore_x_window_hide(tmp->win);
12925        else
12926          ecore_x_window_show(tmp->win);
12927      }
12928
12929    if (bd->comp_hidden == hidden) return;
12930
12931    bd->comp_hidden = hidden;
12932
12933    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12934      {
12935         ecore_x_composite_window_events_disable(bd->win);
12936         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12937      }
12938    else
12939      {
12940         _e_border_shape_input_rectangle_set(bd);
12941         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12942      }
12943 }
12944
12945 EAPI void
12946 e_border_tmp_input_hidden_push(E_Border *bd)
12947 {
12948    E_Border *tmp;
12949    Eina_List *l;
12950
12951    E_OBJECT_CHECK(bd);
12952    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12953
12954    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12955      e_border_tmp_input_hidden_push(tmp);
12956
12957    bd->tmp_input_hidden++;
12958    if (bd->tmp_input_hidden != 1) return;
12959
12960    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12961      {
12962         ecore_x_composite_window_events_disable(bd->win);
12963         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12964      }
12965    else
12966      {
12967         _e_border_shape_input_rectangle_set(bd);
12968         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12969      }
12970 }
12971
12972 EAPI void
12973 e_border_tmp_input_hidden_pop(E_Border *bd)
12974 {
12975    E_Border *tmp;
12976    Eina_List *l;
12977
12978    E_OBJECT_CHECK(bd);
12979    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12980
12981    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12982      e_border_tmp_input_hidden_pop(tmp);
12983
12984    bd->tmp_input_hidden--;
12985    if (bd->tmp_input_hidden != 0) return;
12986
12987    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12988      {
12989         ecore_x_composite_window_events_disable(bd->win);
12990         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12991      }
12992    else
12993      {
12994         _e_border_shape_input_rectangle_set(bd);
12995         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12996      }
12997 }
12998
12999 EAPI void
13000 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
13001 {
13002    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
13003        ((bd->parent) &&
13004         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
13005          ((bd->parent->focused) &&
13006           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
13007        (just_do_it))
13008      {
13009         if (bd->iconic)
13010           {
13011              if (e_config->clientlist_warp_to_iconified_desktop == 1)
13012                e_desk_show(bd->desk);
13013              
13014              if (!bd->lock_user_iconify)
13015                e_border_uniconify(bd);
13016           }
13017         if ((!bd->iconic) && (!bd->sticky))
13018           e_desk_show(bd->desk);
13019         if (!bd->lock_user_stacking) e_border_raise(bd);
13020         if (!bd->lock_focus_out)
13021           {
13022              /* XXX ooffice does send this request for
13023               config dialogs when the main window gets focus.
13024               causing the pointer to jump back and forth.  */
13025              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
13026                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
13027                ecore_x_pointer_warp(bd->zone->container->win,
13028                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
13029              e_border_focus_set(bd, 1, 1);
13030           }
13031      }
13032 }
13033
13034 #ifdef _F_DEICONIFY_APPROVE_
13035 static void
13036 _e_border_window_pending_destroy_event_free(void *data __UNUSED__,
13037                                             void *ev)
13038 {
13039    Ecore_X_Event_Window_Destroy *e;
13040
13041    e = ev;
13042    E_FREE(e);
13043 }
13044
13045 static void
13046 _e_border_window_pending_hide_event_free(void *data __UNUSED__,
13047                                          void *ev)
13048 {
13049    Ecore_X_Event_Window_Hide *e;
13050
13051    e = ev;
13052    E_FREE(e);
13053 }
13054
13055 static void
13056 _e_border_window_pending_hide_event_send(E_Border *bd)
13057 {
13058    Ecore_X_Event_Window_Hide *e;
13059
13060    if (!bd) return;
13061
13062    e = E_NEW(Ecore_X_Event_Window_Hide, 1);
13063    if (e)
13064      {
13065         e->win = bd->client.e.state.pending_event.hide.win;
13066         e->event_win = bd->client.e.state.pending_event.hide.event_win;
13067         e->time = ecore_x_current_time_get();
13068         e->send_event = bd->client.e.state.pending_event.hide.send_event;
13069
13070         ecore_event_add(ECORE_X_EVENT_WINDOW_HIDE, e,
13071                         _e_border_window_pending_hide_event_free, NULL);
13072
13073         ELB(ELBT_BD, "Send pended HIDE event", e->win);
13074      }
13075 }
13076
13077 static void
13078 _e_border_window_pending_destroy_event_send(E_Border *bd)
13079 {
13080    Ecore_X_Event_Window_Destroy *e;
13081
13082    if (!bd) return;
13083
13084    e = E_NEW(Ecore_X_Event_Window_Destroy, 1);
13085    if (e)
13086      {
13087         e->win = bd->client.e.state.pending_event.destroy.win;
13088         e->event_win = bd->client.e.state.pending_event.destroy.event_win;
13089         e->time = ecore_x_current_time_get();
13090
13091         ecore_event_add(ECORE_X_EVENT_WINDOW_DESTROY, e,
13092                         _e_border_window_pending_destroy_event_free, NULL);
13093
13094         ELB(ELBT_BD, "Send pended DESTROY event", e->win);
13095      }
13096 }
13097
13098 static void
13099 _e_border_msg_handler(void       *data,
13100                       const char *name,
13101                       const char *info,
13102                       int         val,
13103                       E_Object   *obj,
13104                       void       *msgdata)
13105 {
13106    E_Manager *man = (E_Manager *)obj;
13107    E_Manager_Comp_Source *src = (E_Manager_Comp_Source *)msgdata;
13108
13109    // handle only comp.manager msg
13110    if (strncmp(name, "comp.manager", sizeof("comp.manager"))) return;
13111
13112    if (!strncmp(info, "visibility.src", sizeof("visibility.src")))
13113      {
13114         Ecore_X_Window win;
13115         E_Border *bd;
13116         Eina_Bool visible;
13117
13118         win = e_manager_comp_src_window_get(man, src);
13119         bd = e_border_find_by_window(win);
13120
13121         if (!bd) return;
13122         if (!bd->client.e.state.deiconify_approve.pending_bd) return;
13123
13124         visible = e_manager_comp_src_visible_get(man, src);
13125         if (visible)
13126           {
13127              E_Border *pending_bd = bd->client.e.state.deiconify_approve.pending_bd;
13128              if (!pending_bd->client.e.state.pending_event.pending)
13129                {
13130                   bd->client.e.state.deiconify_approve.pending_bd = NULL;
13131                   return;
13132                }
13133
13134              pending_bd->client.e.state.pending_event.done = 1;
13135              pending_bd->client.e.state.pending_event.hold_bd = NULL;
13136
13137              if (pending_bd->client.e.state.pending_event.hide.pending)
13138                {
13139                   _e_border_window_pending_hide_event_send(pending_bd);
13140
13141                   // clear hide event data
13142                   pending_bd->client.e.state.pending_event.hide.pending = 0;
13143                   pending_bd->client.e.state.pending_event.hide.win = 0;
13144                   pending_bd->client.e.state.pending_event.hide.event_win = 0;
13145                   pending_bd->client.e.state.pending_event.hide.send_event = 0;
13146                }
13147
13148              if (pending_bd->client.e.state.pending_event.destroy.pending)
13149                {
13150                   _e_border_window_pending_destroy_event_send(pending_bd);
13151
13152                   // clear destroy event data
13153                   pending_bd->client.e.state.pending_event.destroy.pending = 0;
13154                   pending_bd->client.e.state.pending_event.destroy.win = 0;
13155                   pending_bd->client.e.state.pending_event.destroy.event_win = 0;
13156                }
13157
13158              bd->client.e.state.deiconify_approve.pending_bd = NULL;
13159              ELBF(ELBT_ROT, 0, bd->client.win, "RESET pending_bd:%x", bd->client.e.state.deiconify_approve.pending_bd);
13160           }
13161      }
13162 }
13163 #endif
13164 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/