ec137b0fbb3ef7372e04c74f6eb0c757391cdf33
[framework/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    if ((e_config->wm_win_rotation) &&
6020        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
6021        (bd == rot.vkbd) &&
6022        (rot.vkbd_hide_prepare_timer))
6023      {
6024         con = bd->zone->container;
6025         bd = e_border_new(con, e->win, 0, 0);
6026      }
6027
6028    if (bd->iconic)
6029      {
6030         if (!bd->lock_client_iconify)
6031           e_border_uniconify(bd);
6032      }
6033    else
6034      {
6035         /* FIXME: make border "urgent" for a bit - it wants attention */
6036 /*      e_border_show(bd); */
6037           if (!bd->lock_client_stacking)
6038             e_border_raise(bd);
6039      }
6040    return ECORE_CALLBACK_PASS_ON;
6041 }
6042
6043 static Eina_Bool
6044 _e_border_cb_window_destroy(void *data  __UNUSED__,
6045                             int ev_type __UNUSED__,
6046                             void       *ev)
6047 {
6048    E_Border *bd;
6049    Ecore_X_Event_Window_Destroy *e;
6050
6051    e = ev;
6052    bd = e_border_find_by_client_window(e->win);
6053    if (!bd) return ECORE_CALLBACK_PASS_ON;
6054    ELB(ELBT_BD, "X_WIN_DEL", bd->client.win);
6055 #ifdef _F_ZONE_WINDOW_ROTATION_
6056    if (e_config->wm_win_rotation)
6057      {
6058         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
6059           {
6060              ELB(ELBT_BD, "X_DEL_NOTIFY", bd->client.win);
6061              if (!rot.vkbd_hide_prepare_timer)
6062                {
6063                   ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
6064                   e_border_hide(bd, 0);
6065                   if (!rot.vkbd_hide_prepare_timer)
6066                     {
6067                        ELB(ELBT_BD, "DEL VKBD", bd->client.win);
6068                        e_object_del(E_OBJECT(bd));
6069                     }
6070                }
6071              return ECORE_CALLBACK_PASS_ON;
6072           }
6073      }
6074 #endif
6075
6076 #ifdef _F_DEICONIFY_APPROVE_
6077    if (e_config->wm_win_rotation)
6078      {
6079         if (bd->client.e.state.pending_event.pending)
6080           {
6081              bd->client.e.state.pending_event.destroy.pending = 1;
6082              bd->client.e.state.pending_event.destroy.win = e->win;
6083              bd->client.e.state.pending_event.destroy.event_win = e->event_win;
6084              ELB(ELBT_BD, "PENDING destroy event", bd->client.win);
6085              return ECORE_CALLBACK_CANCEL;
6086           }
6087      }
6088
6089    ELB(ELBT_BD, "Real Destroy", bd->client.win);
6090 #endif
6091
6092    e_border_hide(bd, 0);
6093    e_object_del(E_OBJECT(bd));
6094    return ECORE_CALLBACK_PASS_ON;
6095 }
6096
6097 #ifdef _F_DEICONIFY_APPROVE_
6098 static E_Border *
6099 _e_border_find_below_win(E_Border* bd)
6100 {
6101    Eina_List *l;
6102    int i, pos;
6103    Eina_Bool passed;
6104    E_Border *temp_bd;
6105    E_Border *below_bd;
6106
6107    passed = EINA_FALSE;
6108    below_bd = NULL;
6109
6110    E_Border_List *bl;
6111    bl = e_container_border_list_last(bd->zone->container);
6112    while ((temp_bd = e_container_border_list_prev(bl)))
6113      {
6114         /* skip if it's the same border */
6115         if (temp_bd == bd)
6116           {
6117              passed = EINA_TRUE;
6118              continue;
6119           }
6120
6121         if (e_object_is_del(E_OBJECT(temp_bd))) continue;
6122
6123         /* skip if it's not on this zone */
6124         if (temp_bd->zone != bd->zone) continue;
6125
6126         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))
6127           {
6128              if (!temp_bd->client.argb && temp_bd->visible)
6129                {
6130                   below_bd = NULL;
6131                   break;
6132                }
6133           }
6134
6135         if (!passed) continue;
6136
6137         if ((!temp_bd->client.argb) &&
6138             (temp_bd->x == temp_bd->zone->x) &&
6139             (temp_bd->y == temp_bd->zone->y) &&
6140             (temp_bd->w == temp_bd->zone->w) &&
6141             (temp_bd->h == temp_bd->zone->h))
6142           {
6143              if (temp_bd->visible)
6144                {
6145                   below_bd = NULL;
6146                   break;
6147                }
6148
6149              if (ecore_x_window_visible_get(temp_bd->client.win))
6150                {
6151                   below_bd = temp_bd;
6152                   break;
6153                }
6154           }
6155      }
6156    e_container_border_list_free(bl);
6157
6158    return below_bd;
6159 }
6160 #endif
6161
6162 static Eina_Bool
6163 _e_border_cb_window_hide(void *data  __UNUSED__,
6164                          int ev_type __UNUSED__,
6165                          void       *ev)
6166 {
6167    E_Border *bd = NULL;
6168    Ecore_X_Event_Window_Hide *e;
6169
6170    e = ev;
6171 //   printf("HIDE: %x, event %x send: %i\n", e->win, e->event_win, e->send_event);
6172 // not interested in hide events from windows other than the window in question
6173    if (e->win != e->event_win)
6174      {
6175         bd = e_border_find_by_client_window(e->win);
6176         if (!bd) return ECORE_CALLBACK_PASS_ON;
6177         if (!e->send_event) return ECORE_CALLBACK_PASS_ON;
6178         else
6179           {
6180              if (!((bd->zone) &&
6181                    (bd->zone->container->manager->root == e->event_win)))
6182                return ECORE_CALLBACK_PASS_ON;
6183           }
6184      }
6185    if (!bd) bd = e_border_find_by_client_window(e->win);
6186 //   printf("  bd = %p\n", bd);
6187    if (!bd)
6188      {
6189         if (ecore_x_window_visible_get(e->win))
6190           {
6191              ELB(ELBT_BD, "FORCE UNMAP client window", e->win);
6192              ecore_x_window_hide(e->win);
6193           }
6194         return ECORE_CALLBACK_PASS_ON;
6195      }
6196
6197 #ifdef _F_DEICONIFY_APPROVE_
6198    if (e_config->wm_win_rotation)
6199      {
6200         if (bd->client.e.state.pending_event.done)
6201            goto do_hide;
6202
6203         if (bd->client.e.state.pending_event.pending)
6204           {
6205              return ECORE_CALLBACK_CANCEL;
6206           }
6207
6208         if (!E_CONTAINS(bd->x, bd->y, bd->w, bd->h, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
6209            goto do_hide;
6210
6211         E_Border *below_bd;
6212         // 1. find below non-alpha full size win
6213         below_bd = _e_border_find_below_win(bd);
6214
6215         if (below_bd)
6216           {
6217              // 2. check those rotation
6218              bd->client.e.state.pending_event.pending = 1;
6219              bd->client.e.state.pending_event.hold_bd = below_bd;
6220
6221              bd->client.e.state.pending_event.hide.pending = 1;
6222              bd->client.e.state.pending_event.hide.win = e->win;
6223              bd->client.e.state.pending_event.hide.event_win = e->event_win;
6224              bd->client.e.state.pending_event.hide.send_event = e->send_event;
6225
6226              below_bd->client.e.state.deiconify_approve.pending_bd = bd;
6227              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);
6228
6229              // 3. if not same then uniconify
6230              e_border_uniconify(below_bd);
6231
6232              ELB(ELBT_BD, "PENDING hide event", bd->client.win);
6233              return ECORE_CALLBACK_CANCEL;
6234           }
6235      }
6236
6237 do_hide:
6238    bd->client.e.state.pending_event.done = 0;
6239    bd->client.e.state.pending_event.pending = 0;
6240    ELB(ELBT_BD, "Real hide", bd->client.win);
6241 #endif
6242
6243 //   printf("  bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap);
6244    if (bd->ignore_first_unmap > 0)
6245      {
6246         bd->ignore_first_unmap--;
6247         return ECORE_CALLBACK_PASS_ON;
6248      }
6249    /* Don't delete hidden or iconified windows */
6250 #ifdef _F_USE_EXTENDED_ICONIFY_
6251    if (bd->await_hide_event > 0)
6252 #else
6253    if ((bd->iconic) || (bd->await_hide_event > 0))
6254 #endif
6255      {
6256 //        printf("  Don't delete hidden or iconified windows\n");
6257 //        printf("  bd->iconic = %i, bd->visible = %i, bd->new_client = %i, bd->await_hide_event = %i\n",
6258 //               bd->iconic, bd->visible, bd->new_client, bd->await_hide_event);
6259         if (bd->await_hide_event > 0)
6260           {
6261              bd->await_hide_event--;
6262           }
6263         else
6264           {
6265 //             printf("  hide really\n");
6266              /* Only hide the border if it is visible */
6267              if (bd->visible) e_border_hide(bd, 1);
6268           }
6269      }
6270    else
6271      {
6272 //             printf("  hide2\n");
6273 #ifdef _F_USE_EXTENDED_ICONIFY_
6274         if (bd->iconic)
6275           {
6276              bd->iconic = 0;
6277              bd->visible = 1;
6278           }
6279 #endif
6280
6281 #ifdef _F_ZONE_WINDOW_ROTATION_
6282         if (e_config->wm_win_rotation)
6283           {
6284              if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
6285                {
6286                   ELB(ELBT_BD, "X_UNMAP_NOTIFY", bd->client.win);
6287                   if (!rot.vkbd_hide_prepare_timer)
6288                     {
6289                        ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
6290                        e_border_hide(bd, 0);
6291                        if (!rot.vkbd_hide_prepare_timer)
6292                          {
6293                             ELB(ELBT_BD, "DEL VKBD", bd->client.win);
6294                             e_object_del(E_OBJECT(bd));
6295                          }
6296                     }
6297                   return ECORE_CALLBACK_PASS_ON;
6298                }
6299           }
6300 #endif
6301         e_border_hide(bd, 0);
6302         e_object_del(E_OBJECT(bd));
6303      }
6304    return ECORE_CALLBACK_PASS_ON;
6305 }
6306
6307 static Eina_Bool
6308 _e_border_cb_window_reparent(void *data  __UNUSED__,
6309                              int ev_type __UNUSED__,
6310                              void *ev    __UNUSED__)
6311 {
6312 #if 0
6313    E_Border *bd;
6314    Ecore_X_Event_Window_Reparent *e;
6315
6316    e = ev;
6317    bd = e_border_find_by_client_window(e->win);
6318    if (!bd) return 1;
6319    if (e->parent == bd->client.shell_win) return 1;
6320    if (ecore_x_window_parent_get(e->win) == bd->client.shell_win)
6321      {
6322         return 1;
6323      }
6324    e_border_hide(bd, 0);
6325    e_object_del(E_OBJECT(bd));
6326 #endif
6327    return ECORE_CALLBACK_PASS_ON;
6328 }
6329
6330 static Eina_Bool
6331 _e_border_cb_window_configure_request(void *data  __UNUSED__,
6332                                       int ev_type __UNUSED__,
6333                                       void       *ev)
6334 {
6335    E_Border *bd;
6336    Ecore_X_Event_Window_Configure_Request *e;
6337
6338    e = ev;
6339    bd = e_border_find_by_client_window(e->win);
6340    if (!bd)
6341      {
6342         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6343         if (!e_util_container_window_find(e->win))
6344           ecore_x_window_configure(e->win, e->value_mask,
6345                                    e->x, e->y, e->w, e->h, e->border,
6346                                    e->abovewin, e->detail);
6347         return ECORE_CALLBACK_PASS_ON;
6348      }
6349
6350    if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
6351        (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
6352      {
6353         int x, y;
6354
6355         x = bd->x;
6356         y = bd->y;
6357         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
6358           x = e->x;
6359         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
6360           y = e->y;
6361         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6362             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6363           {
6364              int w, h;
6365
6366              h = bd->h;
6367              w = bd->w;
6368              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6369                w = e->w + bd->client_inset.l + bd->client_inset.r;
6370              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6371                h = e->h + bd->client_inset.t + bd->client_inset.b;
6372              if ((!bd->lock_client_location) && (!bd->lock_client_size))
6373                {
6374                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6375                     {
6376                        bd->saved.x = x - bd->zone->x;
6377                        bd->saved.y = y - bd->zone->y;
6378                        bd->saved.w = w;
6379                        bd->saved.h = h;
6380                     }
6381                   else
6382                     e_border_move_resize(bd, x, y, w, h);
6383                }
6384              else if (!bd->lock_client_location)
6385                {
6386                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6387                     {
6388                        bd->saved.x = x - bd->zone->x;
6389                        bd->saved.y = y - bd->zone->y;
6390                     }
6391                   else
6392                     e_border_move(bd, x, y);
6393                }
6394              else if (!bd->lock_client_size)
6395                {
6396                   if ((bd->shaded) || (bd->shading))
6397                     {
6398                        int pw, ph;
6399
6400                        pw = bd->client.w;
6401                        ph = bd->client.h;
6402                        if ((bd->shade.dir == E_DIRECTION_UP) ||
6403                            (bd->shade.dir == E_DIRECTION_DOWN))
6404                          {
6405                             e_border_resize(bd, w, bd->h);
6406                             bd->client.h = ph;
6407                          }
6408                        else
6409                          {
6410                             e_border_resize(bd, bd->w, h);
6411                             bd->client.w = pw;
6412                          }
6413                     }
6414                   else
6415                     {
6416                        if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6417                          {
6418                             bd->saved.w = w;
6419                             bd->saved.h = h;
6420                          }
6421                        else
6422                          e_border_resize(bd, w, h);
6423                     }
6424                }
6425           }
6426         else
6427           {
6428              if (!bd->lock_client_location)
6429                {
6430                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6431                     {
6432                        bd->saved.x = x - bd->zone->x;
6433                        bd->saved.y = y - bd->zone->y;
6434                     }
6435                   else
6436                     e_border_move(bd, x, y);
6437                }
6438           }
6439      }
6440    else if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6441             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6442      {
6443         int w, h;
6444
6445         h = bd->h;
6446         w = bd->w;
6447         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6448           w = e->w + bd->client_inset.l + bd->client_inset.r;
6449         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6450           h = e->h + bd->client_inset.t + bd->client_inset.b;
6451 #ifdef _F_ZONE_WINDOW_ROTATION_
6452         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
6453 #endif
6454         if (!bd->lock_client_size)
6455           {
6456              if ((bd->shaded) || (bd->shading))
6457                {
6458                   int pw, ph;
6459
6460                   pw = bd->client.w;
6461                   ph = bd->client.h;
6462                   if ((bd->shade.dir == E_DIRECTION_UP) ||
6463                       (bd->shade.dir == E_DIRECTION_DOWN))
6464                     {
6465                        e_border_resize(bd, w, bd->h);
6466                        bd->client.h = ph;
6467                     }
6468                   else
6469                     {
6470                        e_border_resize(bd, bd->w, h);
6471                        bd->client.w = pw;
6472                     }
6473                }
6474              else
6475                {
6476                   if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE)
6477                     {
6478                        int zx, zy, zw, zh;
6479                        int rx = bd->x;
6480                        int ry = bd->y;
6481                        zx = zy = zw = zh = 0;
6482
6483      /*
6484       * This code does resize and move a window on a
6485       * X configure request into an useful geometry.
6486       * This is really useful for size jumping file dialogs.
6487       */
6488
6489                        if (bd->zone)
6490                          {
6491                             e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
6492
6493                             if (e_config->geometry_auto_resize_limit == 1)
6494                               {
6495                                  if (w > zw)
6496                                    w = zw;
6497
6498                                  if (h > zh)
6499                                    h = zh;
6500                               }
6501                          }
6502                        e_border_resize(bd, w, h);
6503
6504                        if (e_config->geometry_auto_move == 1)
6505                          {
6506                              /* z{x,y,w,h} are only set here; FIXME! */
6507                              if (bd->zone)
6508                                {
6509                                   // move window horizontal if resize to not useful geometry
6510                                   if (bd->x + bd->w > zx + zw)
6511                                     rx = zx + zw - bd->w;
6512                                   else if (bd->x < zx)
6513                                     rx = zx;
6514
6515                                   // move window vertical if resize to not useful geometry
6516                                   if (bd->y + bd->h > zy + zh)
6517                                     ry = zy + zh - bd->h;
6518                                   else if (bd->y < zy)
6519                                     ry = zy;
6520                                }
6521                              e_border_move(bd, rx, ry);
6522                          }
6523                     }
6524                }
6525           }
6526      }
6527    if (!bd->lock_client_stacking)
6528      {
6529         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
6530             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
6531           {
6532              E_Border *obd;
6533
6534              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6535                {
6536                   obd = e_border_find_by_client_window(e->abovewin);
6537                   if (obd)
6538                     {
6539                        e_border_stack_above(bd, obd);
6540                     }
6541                   else
6542                     {
6543                        ecore_x_window_configure(bd->win,
6544                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6545                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6546                                                 0, 0, 0, 0, 0,
6547                                                 e->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
6548                        /* FIXME: need to rebuiuld border list from current stacking */
6549                     }
6550                }
6551              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6552                {
6553                   obd = e_border_find_by_client_window(e->abovewin);
6554                   if (obd)
6555                     {
6556                        e_border_stack_below(bd, obd);
6557                     }
6558                   else
6559                     {
6560                        ecore_x_window_configure(bd->win,
6561                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6562                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6563                                                 0, 0, 0, 0, 0,
6564                                                 e->abovewin, ECORE_X_WINDOW_STACK_BELOW);
6565                        /* FIXME: need to rebuiuld border list from current stacking */
6566                     }
6567                }
6568              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6569                {
6570      /* FIXME: do */
6571                }
6572              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6573                {
6574      /* FIXME: do */
6575                }
6576              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6577                {
6578      /* FIXME: do */
6579                }
6580           }
6581         else if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
6582           {
6583              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6584                {
6585                   e_border_raise(bd);
6586                }
6587              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6588                {
6589                   e_border_lower(bd);
6590                }
6591              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6592                {
6593      /* FIXME: do */
6594                }
6595              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6596                {
6597      /* FIXME: do */
6598                }
6599              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6600                {
6601      /* FIXME: do */
6602                }
6603           }
6604      }
6605
6606    /* FIXME: need to send synthetic stacking event too as well as move/resize */
6607    _e_border_client_move_resize_send(bd);
6608    return ECORE_CALLBACK_PASS_ON;
6609 }
6610
6611 static Eina_Bool
6612 _e_border_cb_window_resize_request(void *data  __UNUSED__,
6613                                    int ev_type __UNUSED__,
6614                                    void       *ev)
6615 {
6616    E_Border *bd;
6617    Ecore_X_Event_Window_Resize_Request *e;
6618
6619    e = ev;
6620    bd = e_border_find_by_client_window(e->win);
6621    if (!bd)
6622      {
6623         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6624         ecore_x_window_resize(e->win, e->w, e->h);
6625         return ECORE_CALLBACK_PASS_ON;
6626      }
6627    {
6628       int w, h;
6629
6630       w = e->w + bd->client_inset.l + bd->client_inset.r;
6631       h = e->h + bd->client_inset.t + bd->client_inset.b;
6632       if ((bd->shaded) || (bd->shading))
6633         {
6634            int pw, ph;
6635
6636            pw = bd->client.w;
6637            ph = bd->client.h;
6638            if ((bd->shade.dir == E_DIRECTION_UP) ||
6639                (bd->shade.dir == E_DIRECTION_DOWN))
6640              {
6641                 e_border_resize(bd, w, bd->h);
6642                 bd->client.h = ph;
6643              }
6644            else
6645              {
6646                 e_border_resize(bd, bd->w, h);
6647                 bd->client.w = pw;
6648              }
6649         }
6650       else
6651         e_border_resize(bd, w, h);
6652    }
6653
6654    _e_border_client_move_resize_send(bd);
6655    return ECORE_CALLBACK_PASS_ON;
6656 }
6657
6658 static Eina_Bool
6659 _e_border_cb_window_gravity(void *data  __UNUSED__,
6660                             int ev_type __UNUSED__,
6661                             void *ev    __UNUSED__)
6662 {
6663 //   E_Border *bd;
6664 //   Ecore_X_Event_Window_Gravity *e;
6665
6666 //   e = ev;
6667 //   bd = e_border_find_by_client_window(e->win);
6668 //   if (!bd) return 1;
6669              return 1;
6670 }
6671
6672 static Eina_Bool
6673 _e_border_cb_window_stack_request(void *data  __UNUSED__,
6674                                   int ev_type __UNUSED__,
6675                                   void       *ev)
6676 {
6677    E_Border *bd;
6678    Ecore_X_Event_Window_Stack_Request *e;
6679
6680    e = ev;
6681    bd = e_border_find_by_client_window(e->win);
6682    if (!bd)
6683      {
6684         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6685         if (!e_util_container_window_find(e->win))
6686           {
6687              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6688                ecore_x_window_raise(e->win);
6689              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6690                ecore_x_window_lower(e->win);
6691           }
6692         return ECORE_CALLBACK_PASS_ON;
6693      }
6694    if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6695      e_border_raise(bd);
6696    else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6697      e_border_lower(bd);
6698    return ECORE_CALLBACK_PASS_ON;
6699 }
6700
6701 static Eina_Bool
6702 _e_border_cb_window_property(void *data  __UNUSED__,
6703                              int ev_type __UNUSED__,
6704                              void       *ev)
6705 {
6706    E_Border *bd;
6707    Ecore_X_Event_Window_Property *e;
6708
6709    e = ev;
6710    bd = e_border_find_by_client_window(e->win);
6711    if (!bd) return ECORE_CALLBACK_PASS_ON;
6712    if (e->atom == ECORE_X_ATOM_WM_NAME)
6713      {
6714         if ((!bd->client.netwm.name) &&
6715             (!bd->client.netwm.fetch.name))
6716           {
6717              bd->client.icccm.fetch.title = 1;
6718              bd->changed = 1;
6719           }
6720      }
6721    else if (e->atom == ECORE_X_ATOM_NET_WM_NAME)
6722      {
6723         bd->client.netwm.fetch.name = 1;
6724         bd->changed = 1;
6725      }
6726    else if (e->atom == ECORE_X_ATOM_WM_CLASS)
6727      {
6728         bd->client.icccm.fetch.name_class = 1;
6729         bd->changed = 1;
6730      }
6731    else if (e->atom == ECORE_X_ATOM_WM_ICON_NAME)
6732      {
6733         if ((!bd->client.netwm.icon_name) &&
6734             (!bd->client.netwm.fetch.icon_name))
6735           {
6736              bd->client.icccm.fetch.icon_name = 1;
6737              bd->changed = 1;
6738           }
6739      }
6740    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
6741      {
6742         bd->client.netwm.fetch.icon_name = 1;
6743         bd->changed = 1;
6744      }
6745    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
6746      {
6747         bd->client.icccm.fetch.machine = 1;
6748         bd->changed = 1;
6749      }
6750    else if (e->atom == ECORE_X_ATOM_WM_PROTOCOLS)
6751      {
6752         bd->client.icccm.fetch.protocol = 1;
6753         bd->changed = 1;
6754      }
6755    else if (e->atom == ECORE_X_ATOM_WM_HINTS)
6756      {
6757         bd->client.icccm.fetch.hints = 1;
6758         bd->changed = 1;
6759      }
6760    else if (e->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
6761      {
6762         bd->client.icccm.fetch.size_pos_hints = 1;
6763         bd->changed = 1;
6764      }
6765    else if (e->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
6766      {
6767         /*
6768            if ((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN) &&
6769             (!bd->client.netwm.fetch.type))
6770            {
6771          */
6772           bd->client.mwm.fetch.hints = 1;
6773           bd->changed = 1;
6774           /*
6775              }
6776            */
6777      }
6778    else if (e->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
6779      {
6780         bd->client.icccm.fetch.transient_for = 1;
6781         bd->changed = 1;
6782      }
6783    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
6784      {
6785         bd->client.icccm.fetch.client_leader = 1;
6786         bd->changed = 1;
6787      }
6788    else if (e->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
6789      {
6790         bd->client.icccm.fetch.window_role = 1;
6791         bd->changed = 1;
6792      }
6793    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON)
6794      {
6795         bd->client.netwm.fetch.icon = 1;
6796         bd->changed = 1;
6797      }
6798    else if (e->atom == ATM__QTOPIA_SOFT_MENU)
6799      {
6800         bd->client.qtopia.fetch.soft_menu = 1;
6801         bd->changed = 1;
6802      }
6803    else if (e->atom == ATM__QTOPIA_SOFT_MENUS)
6804      {
6805         bd->client.qtopia.fetch.soft_menus = 1;
6806         bd->changed = 1;
6807      }
6808    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
6809      {
6810         bd->client.vkbd.fetch.state = 1;
6811         bd->changed = 1;
6812      }
6813    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
6814      {
6815         bd->client.vkbd.fetch.vkbd = 1;
6816         bd->changed = 1;
6817      }
6818    else if (e->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
6819      {
6820         bd->client.illume.conformant.fetch.conformant = 1;
6821         bd->changed = 1;
6822      }
6823    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
6824      {
6825         bd->client.illume.quickpanel.fetch.state = 1;
6826         bd->changed = 1;
6827      }
6828    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
6829      {
6830         bd->client.illume.quickpanel.fetch.quickpanel = 1;
6831         bd->changed = 1;
6832      }
6833    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
6834      {
6835         bd->client.illume.quickpanel.fetch.priority.major = 1;
6836         bd->changed = 1;
6837      }
6838    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
6839      {
6840         bd->client.illume.quickpanel.fetch.priority.minor = 1;
6841         bd->changed = 1;
6842      }
6843    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
6844      {
6845         bd->client.illume.quickpanel.fetch.zone = 1;
6846         bd->changed = 1;
6847      }
6848    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
6849      {
6850         bd->client.illume.drag.fetch.locked = 1;
6851         bd->changed = 1;
6852      }
6853    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
6854      {
6855         bd->client.illume.drag.fetch.drag = 1;
6856         bd->changed = 1;
6857      }
6858    else if (e->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
6859      {
6860         bd->client.illume.win_state.fetch.state = 1;
6861         bd->changed = 1;
6862      }
6863    /*
6864       else if (e->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
6865       {
6866         bd->client.netwm.fetch.user_time = 1;
6867         bd->changed = 1;
6868       }
6869       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT)
6870       {
6871         bd->client.netwm.fetch.strut = 1;
6872         bd->changed = 1;
6873       }
6874       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
6875       {
6876         bd->client.netwm.fetch.strut = 1;
6877         bd->changed = 1;
6878       }
6879     */
6880    else if (e->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
6881      {
6882         //printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
6883      }
6884    else if (e->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
6885      {
6886         bd->client.e.fetch.video_position = 1;
6887         bd->changed = 1;
6888      }
6889    else if (e->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
6890      {
6891         bd->client.e.fetch.video_parent = 1;
6892         bd->changed = 1;
6893      }
6894    else if (e->atom == ECORE_X_ATOM_NET_WM_STATE)
6895      {
6896         bd->client.netwm.fetch.state = 1;
6897         bd->changed = 1;
6898      }
6899 #ifdef _F_USE_DESK_WINDOW_PROFILE_
6900    else if (e->atom == ECORE_X_ATOM_E_PROFILE_LIST)
6901      {
6902         bd->client.e.fetch.profile_list = 1;
6903         bd->changed = 1;
6904      }
6905 #endif
6906 #ifdef _F_ZONE_WINDOW_ROTATION_
6907    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED)
6908      {
6909         if (e_config->wm_win_rotation)
6910           {
6911              bd->client.e.fetch.rot.support = 1;
6912              bd->changed = 1;
6913           }
6914      }
6915    else if ((e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) ||
6916             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) ||
6917             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) ||
6918             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY))
6919      {
6920         if (e_config->wm_win_rotation)
6921           {
6922              bd->client.e.fetch.rot.geom_hint = 1;
6923              bd->changed = 1;
6924           }
6925      }
6926    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED)
6927      {
6928         if (e_config->wm_win_rotation)
6929           {
6930              bd->client.e.fetch.rot.app_set = 1;
6931              bd->changed = 1;
6932           }
6933      }
6934    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION)
6935      {
6936         if (e_config->wm_win_rotation)
6937           {
6938              bd->client.e.fetch.rot.preferred_rot = 1;
6939              bd->changed = 1;
6940           }
6941      }
6942    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)
6943      {
6944         if (e_config->wm_win_rotation)
6945           {
6946              bd->client.e.fetch.rot.available_rots = 1;
6947              bd->changed = 1;
6948           }
6949      }
6950 #endif
6951
6952    return ECORE_CALLBACK_PASS_ON;
6953 }
6954
6955 static Eina_Bool
6956 _e_border_cb_window_colormap(void *data  __UNUSED__,
6957                              int ev_type __UNUSED__,
6958                              void       *ev)
6959 {
6960    E_Border *bd;
6961    Ecore_X_Event_Window_Colormap *e;
6962
6963    e = ev;
6964    bd = e_border_find_by_client_window(e->win);
6965    if (!bd) return ECORE_CALLBACK_PASS_ON;
6966    return ECORE_CALLBACK_PASS_ON;
6967 }
6968
6969 static Eina_Bool
6970 _e_border_cb_window_shape(void *data  __UNUSED__,
6971                           int ev_type __UNUSED__,
6972                           void       *ev)
6973 {
6974    E_Border *bd;
6975    Ecore_X_Event_Window_Shape *e;
6976
6977    e = ev;
6978    bd = e_border_find_by_client_window(e->win);
6979
6980    if (e->type == ECORE_X_SHAPE_INPUT)
6981      {
6982         if (bd)
6983           {
6984              bd->need_shape_merge = 1;
6985 // YYY             bd->shaped_input = 1;
6986              bd->changes.shape_input = 1;
6987              bd->changed = 1;
6988           }
6989
6990         return ECORE_CALLBACK_PASS_ON;
6991      }
6992
6993    if (bd)
6994      {
6995         bd->changes.shape = 1;
6996         bd->changed = 1;
6997         return ECORE_CALLBACK_PASS_ON;
6998      }
6999    bd = e_border_find_by_window(e->win);
7000    if (bd)
7001      {
7002         bd->need_shape_export = 1;
7003         bd->changed = 1;
7004         return ECORE_CALLBACK_PASS_ON;
7005      }
7006    bd = e_border_find_by_frame_window(e->win);
7007    if (bd)
7008      {
7009         bd->need_shape_merge = 1;
7010         bd->changed = 1;
7011         return ECORE_CALLBACK_PASS_ON;
7012      }
7013    return ECORE_CALLBACK_PASS_ON;
7014 }
7015
7016 static Eina_Bool
7017 _e_border_cb_window_focus_in(void *data  __UNUSED__,
7018                              int ev_type __UNUSED__,
7019                              void       *ev)
7020 {
7021    E_Border *bd;
7022    Ecore_X_Event_Window_Focus_In *e;
7023
7024    e = ev;
7025    bd = e_border_find_by_client_window(e->win);
7026    if (!bd) return ECORE_CALLBACK_PASS_ON;
7027 #ifdef INOUTDEBUG_FOCUS
7028    {
7029       time_t t;
7030       char *ct;
7031
7032       const char *modes[] = {
7033         "MODE_NORMAL",
7034         "MODE_WHILE_GRABBED",
7035         "MODE_GRAB",
7036         "MODE_UNGRAB"
7037       };
7038       const char *details[] = {
7039         "DETAIL_ANCESTOR",
7040         "DETAIL_VIRTUAL",
7041         "DETAIL_INFERIOR",
7042         "DETAIL_NON_LINEAR",
7043         "DETAIL_NON_LINEAR_VIRTUAL",
7044         "DETAIL_POINTER",
7045         "DETAIL_POINTER_ROOT",
7046         "DETAIL_DETAIL_NONE"
7047       };
7048       t = time(NULL);
7049       ct = ctime(&t);
7050       ct[strlen(ct) - 1] = 0;
7051       DBG("FF ->IN %i 0x%x %s md=%s dt=%s\n",
7052              e->time,
7053              e->win,
7054              ct,
7055              modes[e->mode],
7056              details[e->detail]);
7057
7058       DBG("%s cb focus in %d %d\n",
7059              e_border_name_get(bd),
7060              bd->client.icccm.accepts_focus,
7061              bd->client.icccm.take_focus);
7062    }
7063 #endif
7064    _e_border_pri_raise(bd);
7065    if (e->mode == ECORE_X_EVENT_MODE_GRAB)
7066      {
7067         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
7068      }
7069    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
7070      {
7071         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
7072      }
7073
7074    /* ignore focus in from !take_focus windows, we just gave it em */
7075    /* if (!bd->client.icccm.take_focus)
7076     *   return ECORE_CALLBACK_PASS_ON; */
7077
7078    /* should be equal, maybe some clients dont reply with the proper timestamp ? */
7079    if (e->time >= focus_time)
7080      e_border_focus_set(bd, 1, 0);
7081    return ECORE_CALLBACK_PASS_ON;
7082 }
7083
7084 static Eina_Bool
7085 _e_border_cb_window_focus_out(void *data  __UNUSED__,
7086                               int ev_type __UNUSED__,
7087                               void       *ev)
7088 {
7089    E_Border *bd;
7090    Ecore_X_Event_Window_Focus_Out *e;
7091
7092    e = ev;
7093    bd = e_border_find_by_client_window(e->win);
7094    if (!bd) return ECORE_CALLBACK_PASS_ON;
7095 #ifdef INOUTDEBUG_FOCUS
7096    {
7097       time_t t;
7098       char *ct;
7099
7100       const char *modes[] = {
7101         "MODE_NORMAL",
7102         "MODE_WHILE_GRABBED",
7103         "MODE_GRAB",
7104         "MODE_UNGRAB"
7105       };
7106       const char *details[] = {
7107         "DETAIL_ANCESTOR",
7108         "DETAIL_VIRTUAL",
7109         "DETAIL_INFERIOR",
7110         "DETAIL_NON_LINEAR",
7111         "DETAIL_NON_LINEAR_VIRTUAL",
7112         "DETAIL_POINTER",
7113         "DETAIL_POINTER_ROOT",
7114         "DETAIL_DETAIL_NONE"
7115       };
7116       t = time(NULL);
7117       ct = ctime(&t);
7118       ct[strlen(ct) - 1] = 0;
7119       DBG("FF <-OUT %i 0x%x %s md=%s dt=%s",
7120              e->time,
7121              e->win,
7122              ct,
7123              modes[e->mode],
7124              details[e->detail]);
7125
7126       DBG("%s cb focus out %d %d",
7127              e_border_name_get(bd),
7128              bd->client.icccm.accepts_focus,
7129              bd->client.icccm.take_focus);
7130    }
7131 #endif
7132    _e_border_pri_norm(bd);
7133    if (e->mode == ECORE_X_EVENT_MODE_NORMAL)
7134      {
7135         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
7136         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
7137           return ECORE_CALLBACK_PASS_ON;
7138         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
7139           return ECORE_CALLBACK_PASS_ON;
7140      }
7141    else if (e->mode == ECORE_X_EVENT_MODE_GRAB)
7142      {
7143         if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR) return ECORE_CALLBACK_PASS_ON;
7144         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
7145           return ECORE_CALLBACK_PASS_ON;
7146         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
7147           return ECORE_CALLBACK_PASS_ON;
7148         else if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
7149           return ECORE_CALLBACK_PASS_ON;
7150         else if (e->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
7151           return ECORE_CALLBACK_PASS_ON;
7152      }
7153    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
7154      {
7155         /* for firefox/thunderbird (xul) menu walking */
7156         /* NB: why did i disable this before? */
7157         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
7158         else if (e->detail == ECORE_X_EVENT_DETAIL_POINTER)
7159           return ECORE_CALLBACK_PASS_ON;
7160      }
7161    else if (e->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
7162      {
7163         if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR) return ECORE_CALLBACK_PASS_ON;
7164         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
7165           return ECORE_CALLBACK_PASS_ON;
7166      }
7167    e_border_focus_set(bd, 0, 0);
7168    return ECORE_CALLBACK_PASS_ON;
7169 }
7170
7171 #if _F_BORDER_CLIP_TO_ZONE_
7172 static void
7173 _e_border_shape_input_clip_to_zone(E_Border *bd)
7174 {
7175    /* if (!(e_config->window_out_of_vscreen_limits_partly)) return; */
7176    if (!(bd->visible))
7177      return;
7178
7179    if (!(E_CONTAINS(bd->zone->x, bd->zone->y,
7180                     bd->zone->w, bd->zone->h,
7181                     bd->x, bd->y, bd->w, bd->h)))
7182      {
7183         int x, y, w, h;
7184         x = bd->x; y = bd->y; w = bd->w; h = bd->h;
7185         E_RECTS_CLIP_TO_RECT(x, y, w, h,
7186                              bd->zone->x, bd->zone->y,
7187                              bd->zone->w, bd->zone->h);
7188         x -= bd->x;
7189         y -= bd->y;
7190         ecore_x_window_shape_input_rectangle_set(bd->bg_win, x, y, w, h);
7191         ecore_x_window_shape_input_rectangle_set(bd->win, x, y, w, h);
7192      }
7193    else
7194      {
7195         ecore_x_window_shape_input_rectangle_set(bd->bg_win, 0, 0, bd->w, bd->h);
7196         ecore_x_window_shape_input_rectangle_set(bd->win, 0, 0, bd->w, bd->h);
7197      }
7198 }
7199 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
7200
7201 static Eina_Bool
7202 _e_border_cb_client_message(void *data  __UNUSED__,
7203                             int ev_type __UNUSED__,
7204                             void       *ev)
7205 {
7206    Ecore_X_Event_Client_Message *e;
7207    E_Border *bd;
7208
7209    e = ev;
7210 #ifdef _F_DEICONIFY_APPROVE_
7211    if (e->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
7212      {
7213         if (!e_config->deiconify_approve) return ECORE_CALLBACK_PASS_ON;
7214
7215         bd = e_border_find_by_client_window(e->win);
7216         if (bd)
7217           {
7218              if (bd->client.e.state.deiconify_approve.support)
7219                {
7220                   if (e->data.l[1] != 1) return ECORE_CALLBACK_PASS_ON;
7221                   bd->client.e.state.deiconify_approve.render_done = 1;
7222
7223                   E_Border *ancestor_bd;
7224                   ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
7225                   if (ancestor_bd)
7226                     {
7227                        ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
7228                        bd->client.e.state.deiconify_approve.ancestor = NULL;
7229                     }
7230                   else
7231                     {
7232                        ancestor_bd = bd;
7233                     }
7234
7235                   ELBF(ELBT_BD, 0, bd->client.win,
7236                        "RECEIVE DEICONIFY_APPROVE.. ancestor:%x", ancestor_bd->client.win);
7237
7238                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
7239                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
7240                     {
7241                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
7242                          {
7243                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
7244                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
7245
7246                             if (bd->client.e.state.deiconify_approve.wait_timer)
7247                               {
7248                                  ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer);
7249                                  bd->client.e.state.deiconify_approve.wait_timer = NULL;
7250                               }
7251
7252                             e_border_uniconify(ancestor_bd);
7253                          }
7254                        else
7255                          {
7256                             ELB(ELBT_BD, "Unset DEICONIFY_APPROVE render_done", ancestor_bd->client.win);
7257                             ancestor_bd->client.e.state.deiconify_approve.render_done = 0;
7258                          }
7259                     }
7260
7261                   if (bd != ancestor_bd)
7262                     {
7263                        if (bd->client.e.state.deiconify_approve.wait_timer)
7264                          {
7265                             ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer);
7266                             bd->client.e.state.deiconify_approve.wait_timer = NULL;
7267                          }
7268                     }
7269                }
7270           }
7271         return ECORE_CALLBACK_PASS_ON;
7272      }
7273 #endif
7274
7275 #ifdef _F_ZONE_WINDOW_ROTATION_
7276    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
7277
7278    bd = e_border_find_by_client_window(e->win);
7279    if (!bd)
7280      {
7281         if (e_config->wm_win_rotation)
7282           {
7283              Ecore_X_Event_Client_Message *msg = NULL;
7284              Ecore_X_Atom t = e->message_type;
7285              if ((t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)  ||
7286                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE) ||
7287                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)   ||
7288                  (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE))
7289                {
7290                   msg = E_NEW(Ecore_X_Event_Client_Message, 1);
7291                   if (!msg) return ECORE_CALLBACK_PASS_ON;
7292
7293                   msg->win = e->win;
7294                   msg->message_type = e->message_type;
7295                   msg->data.l[0] = e->data.l[0];
7296                   msg->data.l[1] = e->data.l[1];
7297                   msg->data.l[2] = e->data.l[2];
7298                   msg->data.l[3] = e->data.l[3];
7299                   msg->data.l[4] = e->data.l[4];
7300                   rot.msgs = eina_list_append(rot.msgs, msg);
7301
7302                   rot.fetch = EINA_TRUE;
7303                }
7304           }
7305         return ECORE_CALLBACK_PASS_ON;
7306      }
7307
7308    if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE)
7309      {
7310         ELBF(ELBT_ROT, 0, e->data.l[0], "GET ROT_DONE a%d %dx%d zone_a:%d",
7311              e->data.l[1], e->data.l[2], e->data.l[3], bd->zone->rot.curr);
7312
7313         if (e_config->wm_win_rotation)
7314           {
7315              if ((int)e->data.l[1] == bd->client.e.state.rot.curr)
7316                {
7317                   _e_border_rotation_list_remove(bd);
7318                   if (bd->client.e.state.rot.pending_show)
7319                     {
7320                        ELB(ELBT_BD, "SHOW_BD (PEND)", bd->client.win);
7321                        e_border_show(bd);
7322 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
7323                        if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
7324                          _e_border_check_stack(bd);
7325 #endif
7326                        bd->client.e.state.rot.pending_show = 0;
7327                     }
7328                }
7329           }
7330      }
7331 #endif
7332    return ECORE_CALLBACK_PASS_ON;
7333 }
7334
7335 static Eina_Bool
7336 _e_border_cb_window_state_request(void *data  __UNUSED__,
7337                                   int ev_type __UNUSED__,
7338                                   void       *ev)
7339 {
7340    E_Border *bd;
7341    Ecore_X_Event_Window_State_Request *e;
7342    int i;
7343
7344    e = ev;
7345    bd = e_border_find_by_client_window(e->win);
7346    if (!bd) return ECORE_CALLBACK_PASS_ON;
7347
7348    for (i = 0; i < 2; i++)
7349      e_hints_window_state_update(bd, e->state[i], e->action);
7350
7351    return ECORE_CALLBACK_PASS_ON;
7352 }
7353
7354 static Eina_Bool
7355 _e_border_cb_window_move_resize_request(void *data  __UNUSED__,
7356                                         int ev_type __UNUSED__,
7357                                         void       *ev)
7358 {
7359    E_Border *bd;
7360    Ecore_X_Event_Window_Move_Resize_Request *e;
7361
7362    e = ev;
7363    bd = e_border_find_by_client_window(e->win);
7364    if (!bd) return ECORE_CALLBACK_PASS_ON;
7365
7366    if ((bd->shaded) || (bd->shading) ||
7367        (bd->fullscreen) || (bd->moving) ||
7368        (bd->resize_mode != RESIZE_NONE))
7369      return ECORE_CALLBACK_PASS_ON;
7370
7371    if ((e->button >= 1) && (e->button <= 3))
7372      {
7373         bd->mouse.last_down[e->button - 1].mx = e->x;
7374         bd->mouse.last_down[e->button - 1].my = e->y;
7375         bd->mouse.last_down[e->button - 1].x = bd->x;
7376         bd->mouse.last_down[e->button - 1].y = bd->y;
7377         bd->mouse.last_down[e->button - 1].w = bd->w;
7378         bd->mouse.last_down[e->button - 1].h = bd->h;
7379      }
7380    else
7381      {
7382         bd->moveinfo.down.x = bd->x;
7383         bd->moveinfo.down.y = bd->y;
7384         bd->moveinfo.down.w = bd->w;
7385         bd->moveinfo.down.h = bd->h;
7386      }
7387    bd->mouse.current.mx = e->x;
7388    bd->mouse.current.my = e->y;
7389    bd->moveinfo.down.button = e->button;
7390    bd->moveinfo.down.mx = e->x;
7391    bd->moveinfo.down.my = e->y;
7392    grabbed = 1;
7393
7394    if (!bd->lock_user_stacking)
7395      e_border_raise(bd);
7396
7397    if (e->direction == MOVE)
7398      {
7399         bd->cur_mouse_action = e_action_find("window_move");
7400         if (bd->cur_mouse_action)
7401           {
7402              if ((!bd->cur_mouse_action->func.end_mouse) &&
7403                  (!bd->cur_mouse_action->func.end))
7404                bd->cur_mouse_action = NULL;
7405              if (bd->cur_mouse_action)
7406                {
7407                   e_object_ref(E_OBJECT(bd->cur_mouse_action));
7408                   bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
7409                }
7410           }
7411         return ECORE_CALLBACK_PASS_ON;
7412      }
7413
7414    if (!_e_border_resize_begin(bd))
7415      return ECORE_CALLBACK_PASS_ON;
7416
7417    switch (e->direction)
7418      {
7419       case RESIZE_TL:
7420         bd->resize_mode = RESIZE_TL;
7421         GRAV_SET(bd, ECORE_X_GRAVITY_SE);
7422         break;
7423
7424       case RESIZE_T:
7425         bd->resize_mode = RESIZE_T;
7426         GRAV_SET(bd, ECORE_X_GRAVITY_S);
7427         break;
7428
7429       case RESIZE_TR:
7430         bd->resize_mode = RESIZE_TR;
7431         GRAV_SET(bd, ECORE_X_GRAVITY_SW);
7432         break;
7433
7434       case RESIZE_R:
7435         bd->resize_mode = RESIZE_R;
7436         GRAV_SET(bd, ECORE_X_GRAVITY_W);
7437         break;
7438
7439       case RESIZE_BR:
7440         bd->resize_mode = RESIZE_BR;
7441         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
7442         break;
7443
7444       case RESIZE_B:
7445         bd->resize_mode = RESIZE_B;
7446         GRAV_SET(bd, ECORE_X_GRAVITY_N);
7447         break;
7448
7449       case RESIZE_BL:
7450         bd->resize_mode = RESIZE_BL;
7451         GRAV_SET(bd, ECORE_X_GRAVITY_NE);
7452         break;
7453
7454       case RESIZE_L:
7455         bd->resize_mode = RESIZE_L;
7456         GRAV_SET(bd, ECORE_X_GRAVITY_E);
7457         break;
7458
7459       default:
7460         return ECORE_CALLBACK_PASS_ON;
7461      }
7462
7463    bd->cur_mouse_action = e_action_find("window_resize");
7464    if (bd->cur_mouse_action)
7465      {
7466         if ((!bd->cur_mouse_action->func.end_mouse) &&
7467             (!bd->cur_mouse_action->func.end))
7468           bd->cur_mouse_action = NULL;
7469      }
7470    if (bd->cur_mouse_action)
7471      e_object_ref(E_OBJECT(bd->cur_mouse_action));
7472
7473    return ECORE_CALLBACK_PASS_ON;
7474 }
7475
7476 static Eina_Bool
7477 _e_border_cb_desktop_change(void *data  __UNUSED__,
7478                             int ev_type __UNUSED__,
7479                             void       *ev)
7480 {
7481    E_Border *bd;
7482    Ecore_X_Event_Desktop_Change *e;
7483
7484    e = ev;
7485    bd = e_border_find_by_client_window(e->win);
7486    if (bd)
7487      {
7488         if (e->desk == 0xffffffff)
7489           e_border_stick(bd);
7490         else if ((int)e->desk < (bd->zone->desk_x_count * bd->zone->desk_y_count))
7491           {
7492              E_Desk *desk;
7493
7494              desk = e_desk_at_pos_get(bd->zone, e->desk);
7495              if (desk)
7496                e_border_desk_set(bd, desk);
7497           }
7498      }
7499    else
7500      {
7501         ecore_x_netwm_desktop_set(e->win, e->desk);
7502      }
7503    return ECORE_CALLBACK_PASS_ON;
7504 }
7505
7506 static Eina_Bool
7507 _e_border_cb_sync_alarm(void *data  __UNUSED__,
7508                         int ev_type __UNUSED__,
7509                         void       *ev)
7510 {
7511    E_Border *bd;
7512    Ecore_X_Event_Sync_Alarm *e;
7513    unsigned int serial;
7514
7515    e = ev;
7516    bd = e_border_find_by_alarm(e->alarm);
7517    if (!bd) return ECORE_CALLBACK_PASS_ON;
7518
7519    if (bd->client.netwm.sync.wait)
7520      bd->client.netwm.sync.wait--;
7521
7522    if (ecore_x_sync_counter_query(bd->client.netwm.sync.counter, &serial))
7523      {
7524         E_Border_Pending_Move_Resize *pnd = NULL;
7525
7526         /* skip pending for which we didn't get a reply */
7527         while (bd->pending_move_resize)
7528           {
7529              pnd = bd->pending_move_resize->data;
7530              bd->pending_move_resize = eina_list_remove(bd->pending_move_resize, pnd);
7531
7532              if (serial == pnd->serial)
7533                break;
7534
7535              E_FREE(pnd);
7536           }
7537
7538         if (pnd)
7539           {
7540              bd->x = pnd->x;
7541              bd->y = pnd->y;
7542              bd->w = pnd->w;
7543              bd->h = pnd->h;
7544              bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
7545              bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
7546              E_FREE(pnd);
7547           }
7548      }
7549
7550    bd->changes.size = 1;
7551    bd->changes.pos = 1;
7552
7553    _e_border_eval(bd);
7554    evas_render(bd->bg_evas);
7555
7556    ecore_x_pointer_xy_get(e_manager_current_get()->root,
7557                           &bd->mouse.current.mx,
7558                           &bd->mouse.current.my);
7559
7560    bd->client.netwm.sync.send_time = ecore_loop_time_get();
7561    _e_border_resize_handle(bd);
7562
7563    return ECORE_CALLBACK_PASS_ON;
7564 }
7565
7566 static Eina_Bool
7567 _e_border_cb_efreet_cache_update(void *data  __UNUSED__,
7568                                  int ev_type __UNUSED__,
7569                                  void *ev    __UNUSED__)
7570 {
7571    Eina_List *l;
7572    E_Border *bd;
7573
7574    /* mark all borders for desktop/icon updates */
7575    EINA_LIST_FOREACH(borders, l, bd)
7576      {
7577         if (bd->desktop)
7578           {
7579              efreet_desktop_free(bd->desktop);
7580              bd->desktop = NULL;
7581           }
7582         bd->changes.icon = 1;
7583         bd->changed = 1;
7584      }
7585    /*
7586       e_init_status_set(_("Desktop files scan done"));
7587       e_init_done();
7588     */
7589    return ECORE_CALLBACK_PASS_ON;
7590 }
7591
7592 static Eina_Bool
7593 _e_border_cb_config_icon_theme(void *data  __UNUSED__,
7594                                int ev_type __UNUSED__,
7595                                void *ev    __UNUSED__)
7596 {
7597    Eina_List *l;
7598    E_Border *bd;
7599
7600    /* mark all borders for desktop/icon updates */
7601    EINA_LIST_FOREACH(borders, l, bd)
7602      {
7603         bd->changes.icon = 1;
7604         bd->changed = 1;
7605      }
7606    return ECORE_CALLBACK_PASS_ON;
7607 }
7608
7609 static Eina_Bool
7610 _e_border_cb_pointer_warp(void *data  __UNUSED__,
7611                           int ev_type __UNUSED__,
7612                           void       *ev)
7613 {
7614    E_Event_Pointer_Warp *e;
7615
7616    e = ev;
7617    if (!bdmove) return ECORE_CALLBACK_PASS_ON;
7618    e_border_move(bdmove, bdmove->x + (e->curr.x - e->prev.x), bdmove->y + (e->curr.y - e->prev.y));
7619    return ECORE_CALLBACK_PASS_ON;
7620 }
7621
7622 static void
7623 _e_border_cb_signal_bind(void            *data,
7624                          Evas_Object *obj __UNUSED__,
7625                          const char      *emission,
7626                          const char      *source)
7627 {
7628    E_Border *bd;
7629
7630    bd = data;
7631    if (e_dnd_active()) return;
7632    e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd),
7633                             emission, source);
7634 }
7635
7636 static Eina_Bool
7637 _e_border_cb_mouse_in(void    *data,
7638                       int type __UNUSED__,
7639                       void    *event)
7640 {
7641    Ecore_X_Event_Mouse_In *ev;
7642    E_Border *bd;
7643
7644    ev = event;
7645    bd = data;
7646 #ifdef INOUTDEBUG_MOUSE
7647    {
7648       time_t t;
7649       char *ct;
7650
7651       const char *modes[] = {
7652          "MODE_NORMAL",
7653          "MODE_WHILE_GRABBED",
7654          "MODE_GRAB",
7655          "MODE_UNGRAB"
7656       };
7657       const char *details[] = {
7658          "DETAIL_ANCESTOR",
7659          "DETAIL_VIRTUAL",
7660          "DETAIL_INFERIOR",
7661          "DETAIL_NON_LINEAR",
7662          "DETAIL_NON_LINEAR_VIRTUAL",
7663          "DETAIL_POINTER",
7664          "DETAIL_POINTER_ROOT",
7665          "DETAIL_DETAIL_NONE"
7666       };
7667       t = time(NULL);
7668       ct = ctime(&t);
7669       ct[strlen(ct) - 1] = 0;
7670       DBG("@@ ->IN 0x%x 0x%x %s md=%s dt=%s",
7671              ev->win, ev->event_win,
7672              ct,
7673              modes[ev->mode],
7674              details[ev->detail]);
7675    }
7676 #endif
7677    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7678    if (ev->event_win == bd->win)
7679      {
7680         e_focus_event_mouse_in(bd);
7681      }
7682 #if 0
7683    if ((ev->win != bd->win) &&
7684        (ev->win != bd->event_win) &&
7685        (ev->event_win != bd->win) &&
7686        (ev->event_win != bd->event_win))
7687      return ECORE_CALLBACK_PASS_ON;
7688 #else
7689    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7690 #endif
7691    bd->mouse.current.mx = ev->root.x;
7692    bd->mouse.current.my = ev->root.y;
7693    if (!bd->bg_evas_in)
7694      {
7695         evas_event_feed_mouse_in(bd->bg_evas, ev->time, NULL);
7696         bd->bg_evas_in = EINA_TRUE;
7697      }
7698    return ECORE_CALLBACK_PASS_ON;
7699 }
7700
7701 static Eina_Bool
7702 _e_border_cb_mouse_out(void    *data,
7703                        int type __UNUSED__,
7704                        void    *event)
7705 {
7706    Ecore_X_Event_Mouse_Out *ev;
7707    E_Border *bd;
7708
7709    ev = event;
7710    bd = data;
7711 #ifdef INOUTDEBUG_MOUSE
7712    {
7713       time_t t;
7714       char *ct;
7715
7716       const char *modes[] = {
7717          "MODE_NORMAL",
7718          "MODE_WHILE_GRABBED",
7719          "MODE_GRAB",
7720          "MODE_UNGRAB"
7721       };
7722       const char *details[] = {
7723          "DETAIL_ANCESTOR",
7724          "DETAIL_VIRTUAL",
7725          "DETAIL_INFERIOR",
7726          "DETAIL_NON_LINEAR",
7727          "DETAIL_NON_LINEAR_VIRTUAL",
7728          "DETAIL_POINTER",
7729          "DETAIL_POINTER_ROOT",
7730          "DETAIL_DETAIL_NONE"
7731       };
7732       t = time(NULL);
7733       ct = ctime(&t);
7734       ct[strlen(ct) - 1] = 0;
7735       DBG("@@ <-OUT 0x%x 0x%x %s md=%s dt=%s",
7736              ev->win, ev->event_win,
7737              ct,
7738              modes[ev->mode],
7739              details[ev->detail]);
7740    }
7741 #endif
7742    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7743    if (ev->event_win == bd->win)
7744      {
7745         if (bd->fullscreen)
7746           return ECORE_CALLBACK_PASS_ON;
7747         if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
7748             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7749           return ECORE_CALLBACK_PASS_ON;
7750         if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7751           return ECORE_CALLBACK_PASS_ON;
7752         if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
7753             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7754           return ECORE_CALLBACK_PASS_ON;
7755         e_focus_event_mouse_out(bd);
7756      }
7757 #if 0
7758    if ((ev->win != bd->win) &&
7759        (ev->win != bd->event_win) &&
7760        (ev->event_win != bd->win) &&
7761        (ev->event_win != bd->event_win))
7762      return ECORE_CALLBACK_PASS_ON;
7763 #else
7764    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7765 #endif
7766    bd->mouse.current.mx = ev->root.x;
7767    bd->mouse.current.my = ev->root.y;
7768    if (bd->bg_evas_in)
7769      {
7770         if (!((evas_event_down_count_get(bd->bg_evas) > 0) &&
7771               (!((ev->mode == ECORE_X_EVENT_MODE_GRAB) &&
7772                  (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)))))
7773           {
7774              if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7775                evas_event_feed_mouse_cancel(bd->bg_evas, ev->time, NULL);
7776              evas_event_feed_mouse_out(bd->bg_evas, ev->time, NULL);
7777              bd->bg_evas_in = EINA_FALSE;
7778           }
7779      }
7780    return ECORE_CALLBACK_PASS_ON;
7781 }
7782
7783 static Eina_Bool
7784 _e_border_cb_mouse_wheel(void    *data,
7785                          int type __UNUSED__,
7786                          void    *event)
7787 {
7788    Ecore_Event_Mouse_Wheel *ev;
7789    E_Border *bd;
7790
7791    ev = event;
7792    bd = data;
7793    if ((ev->event_window == bd->win) ||
7794        (ev->event_window == bd->event_win))
7795      {
7796         bd->mouse.current.mx = ev->root.x;
7797         bd->mouse.current.my = ev->root.y;
7798         if (!bd->cur_mouse_action)
7799           e_bindings_wheel_event_handle(E_BINDING_CONTEXT_WINDOW,
7800                                         E_OBJECT(bd), ev);
7801      }
7802    evas_event_feed_mouse_wheel(bd->bg_evas, ev->direction, ev->z, ev->timestamp, NULL);
7803    return ECORE_CALLBACK_PASS_ON;
7804 }
7805
7806 static Eina_Bool
7807 _e_border_cb_mouse_down(void    *data,
7808                         int type __UNUSED__,
7809                         void    *event)
7810 {
7811    Ecore_Event_Mouse_Button *ev;
7812    E_Border *bd;
7813
7814    ev = event;
7815    bd = data;
7816    if ((ev->event_window == bd->win) ||
7817        (ev->event_window == bd->event_win))
7818      {
7819         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7820           {
7821              bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7822              bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7823              bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7824              bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7825              bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7826              bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7827           }
7828         else
7829           {
7830              bd->moveinfo.down.x = bd->x + bd->fx.x;
7831              bd->moveinfo.down.y = bd->y + bd->fx.y;
7832              bd->moveinfo.down.w = bd->w;
7833              bd->moveinfo.down.h = bd->h;
7834           }
7835         bd->mouse.current.mx = ev->root.x;
7836         bd->mouse.current.my = ev->root.y;
7837         if (!bd->cur_mouse_action)
7838           {
7839              bd->cur_mouse_action =
7840                e_bindings_mouse_down_event_handle(E_BINDING_CONTEXT_WINDOW,
7841                                                   E_OBJECT(bd), ev);
7842              if (bd->cur_mouse_action)
7843                {
7844                   if ((!bd->cur_mouse_action->func.end_mouse) &&
7845                       (!bd->cur_mouse_action->func.end))
7846                     bd->cur_mouse_action = NULL;
7847                   if (bd->cur_mouse_action)
7848                     e_object_ref(E_OBJECT(bd->cur_mouse_action));
7849                }
7850           }
7851         e_focus_event_mouse_down(bd);
7852      }
7853    if (ev->window != ev->event_window)
7854      {
7855         return 1;
7856      }
7857    if ((ev->window != bd->event_win) && (ev->event_window != bd->win))
7858      {
7859         return 1;
7860      }
7861    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7862      {
7863         bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7864         bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7865         bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7866         bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7867         bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7868         bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7869      }
7870    else
7871      {
7872         bd->moveinfo.down.x = bd->x + bd->fx.x;
7873         bd->moveinfo.down.y = bd->y + bd->fx.y;
7874         bd->moveinfo.down.w = bd->w;
7875         bd->moveinfo.down.h = bd->h;
7876      }
7877    bd->mouse.current.mx = ev->root.x;
7878    bd->mouse.current.my = ev->root.y;
7879 /*
7880    if (bd->moving)
7881      {
7882      }
7883    else if (bd->resize_mode != RESIZE_NONE)
7884      {
7885      }
7886    else
7887  */
7888    {
7889       Evas_Button_Flags flags = EVAS_BUTTON_NONE;
7890
7891       if (ev->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
7892       if (ev->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
7893       evas_event_feed_mouse_down(bd->bg_evas, ev->buttons, flags, ev->timestamp, NULL);
7894    }
7895    return ECORE_CALLBACK_PASS_ON;
7896 }
7897
7898 static Eina_Bool
7899 _e_border_cb_mouse_up(void    *data,
7900                       int type __UNUSED__,
7901                       void    *event)
7902 {
7903    Ecore_Event_Mouse_Button *ev;
7904    E_Border *bd;
7905
7906    ev = event;
7907    bd = data;
7908    if ((ev->event_window == bd->win) ||
7909        (ev->event_window == bd->event_win))
7910      {
7911         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7912           {
7913              bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7914              bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7915              bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7916              bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7917           }
7918         bd->mouse.current.mx = ev->root.x;
7919         bd->mouse.current.my = ev->root.y;
7920         /* also we dont pass the same params that went in - then again that */
7921         /* should be ok as we are just ending the action if it has an end */
7922         if (bd->cur_mouse_action)
7923           {
7924              if (bd->cur_mouse_action->func.end_mouse)
7925                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", ev);
7926              else if (bd->cur_mouse_action->func.end)
7927                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
7928              e_object_unref(E_OBJECT(bd->cur_mouse_action));
7929              bd->cur_mouse_action = NULL;
7930           }
7931         else
7932           {
7933              if (!e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd), ev))
7934                e_focus_event_mouse_up(bd);
7935           }
7936      }
7937    if (ev->window != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7938    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7939      {
7940         bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7941         bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7942         bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7943         bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7944      }
7945    bd->mouse.current.mx = ev->root.x;
7946    bd->mouse.current.my = ev->root.y;
7947
7948    bd->drag.start = 0;
7949
7950    evas_event_feed_mouse_up(bd->bg_evas, ev->buttons, EVAS_BUTTON_NONE, ev->timestamp, NULL);
7951    return ECORE_CALLBACK_PASS_ON;
7952 }
7953
7954 static void
7955 _e_border_stay_within_container(E_Border *bd, int x, int y, int *new_x, int *new_y)
7956 {
7957 #ifdef _F_BORDER_CLIP_TO_ZONE_
7958    int new_x_max, new_y_max;
7959    int new_x_min, new_y_min;
7960    int margin_x, margin_y;
7961
7962    margin_x = bd->w - 100;
7963    margin_y = bd->h - 100;
7964
7965    new_x_max = bd->zone->x + bd->zone->w - bd->w + margin_x;
7966    new_x_min = bd->zone->x - margin_x;
7967    new_y_max = bd->zone->y + bd->zone->h - bd->h + margin_y;
7968    new_y_min = bd->zone->y - margin_y;
7969
7970    if (x >= new_x_max)      *new_x = new_x_max;
7971    else if (x <= new_x_min) *new_x = new_x_min;
7972
7973    if (y >= new_y_max)      *new_y = new_y_max;
7974    else if (y <= new_y_min) *new_y = new_y_min;
7975 #endif
7976 }
7977
7978 static Eina_Bool
7979 _e_border_cb_mouse_move(void    *data,
7980                         int type __UNUSED__,
7981                         void    *event)
7982 {
7983    Ecore_Event_Mouse_Move *ev;
7984    E_Border *bd;
7985
7986    ev = event;
7987    bd = data;
7988    if ((ev->window != bd->event_win) &&
7989        (ev->event_window != bd->win)) return ECORE_CALLBACK_PASS_ON;
7990    bd->mouse.current.mx = ev->root.x;
7991    bd->mouse.current.my = ev->root.y;
7992    if (bd->moving)
7993      {
7994         int x, y, new_x, new_y;
7995         int new_w, new_h;
7996         Eina_List *skiplist = NULL;
7997 #if 0
7998         // FIXME: remove? sync what for when only moving?
7999         if ((ecore_loop_time_get() - bd->client.netwm.sync.time) > 0.5)
8000           bd->client.netwm.sync.wait = 0;
8001         if ((bd->client.netwm.sync.request) &&
8002             (bd->client.netwm.sync.alarm) &&
8003             (bd->client.netwm.sync.wait > 1)) return ECORE_CALLBACK_PASS_ON;
8004 #endif
8005         if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
8006           {
8007              x = bd->mouse.last_down[bd->moveinfo.down.button - 1].x +
8008                (bd->mouse.current.mx - bd->moveinfo.down.mx);
8009              y = bd->mouse.last_down[bd->moveinfo.down.button - 1].y +
8010                (bd->mouse.current.my - bd->moveinfo.down.my);
8011           }
8012         else
8013           {
8014              x = bd->moveinfo.down.x +
8015                (bd->mouse.current.mx - bd->moveinfo.down.mx);
8016              y = bd->moveinfo.down.y +
8017                (bd->mouse.current.my - bd->moveinfo.down.my);
8018           }
8019         new_x = x;
8020         new_y = y;
8021
8022 #ifdef _F_USE_RESIST_MAGNETIC_EFFECT_
8023         skiplist = eina_list_append(skiplist, bd);
8024         e_resist_container_border_position(bd->zone->container, skiplist,
8025                                            bd->x, bd->y, bd->w, bd->h,
8026                                            x, y, bd->w, bd->h,
8027                                            &new_x, &new_y, &new_w, &new_h);
8028         eina_list_free(skiplist);
8029
8030         _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
8031 #else
8032         /* if (e_config->window_out_of_vscreen_limits_partly) */
8033         if (1)
8034           _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
8035         else
8036           {
8037              skiplist = eina_list_append(skiplist, bd);
8038              e_resist_container_border_position(bd->zone->container, skiplist,
8039                                                 bd->x, bd->y, bd->w, bd->h,
8040                                                 x, y, bd->w, bd->h,
8041                                                 &new_x, &new_y, &new_w, &new_h);
8042              eina_list_free(skiplist);
8043           }
8044 #endif
8045         bd->shelf_fix.x = 0;
8046         bd->shelf_fix.y = 0;
8047         bd->shelf_fix.modified = 0;
8048         e_border_move(bd, new_x, new_y);
8049         e_zone_flip_coords_handle(bd->zone, ev->root.x, ev->root.y);
8050      }
8051    else if (bd->resize_mode != RESIZE_NONE)
8052      {
8053         if ((bd->client.netwm.sync.request) &&
8054             (bd->client.netwm.sync.alarm))
8055           {
8056              if ((ecore_loop_time_get() - bd->client.netwm.sync.send_time) > 0.5)
8057                {
8058                   E_Border_Pending_Move_Resize *pnd;
8059
8060                   if (bd->pending_move_resize)
8061                     {
8062                        bd->changes.pos = 1;
8063                        bd->changes.size = 1;
8064                        bd->changed = 1;
8065                        _e_border_client_move_resize_send(bd);
8066                     }
8067                   EINA_LIST_FREE(bd->pending_move_resize, pnd)
8068                     E_FREE(pnd);
8069
8070                   bd->client.netwm.sync.wait = 0;
8071                }
8072              /* sync.wait is incremented when resize_handle sends
8073               * sync-request and decremented by sync-alarm cb. so
8074               * we resize here either on initial resize, timeout or
8075               * when no new resize-request was added by sync-alarm cb.
8076               */
8077              if (!bd->client.netwm.sync.wait)
8078                _e_border_resize_handle(bd);
8079           }
8080         else
8081           _e_border_resize_handle(bd);
8082      }
8083    else
8084      {
8085         if (bd->drag.start)
8086           {
8087              if ((bd->drag.x == -1) && (bd->drag.y == -1))
8088                {
8089                   bd->drag.x = ev->root.x;
8090                   bd->drag.y = ev->root.y;
8091                }
8092              else
8093                {
8094                   int dx, dy;
8095
8096                   dx = bd->drag.x - ev->root.x;
8097                   dy = bd->drag.y - ev->root.y;
8098                   if (((dx * dx) + (dy * dy)) >
8099                       (e_config->drag_resist * e_config->drag_resist))
8100                     {
8101      /* start drag! */
8102                         if (bd->icon_object)
8103                           {
8104                              Evas_Object *o = NULL;
8105                              Evas_Coord x, y, w, h;
8106                              const char *drag_types[] = { "enlightenment/border" };
8107
8108                              e_object_ref(E_OBJECT(bd));
8109                              evas_object_geometry_get(bd->icon_object,
8110                                                       &x, &y, &w, &h);
8111                              drag_border = e_drag_new(bd->zone->container,
8112                                                       bd->x + bd->fx.x + x,
8113                                                       bd->y + bd->fx.y + y,
8114                                                       drag_types, 1, bd, -1,
8115                                                       NULL,
8116                                                       _e_border_cb_drag_finished);
8117                              o = e_border_icon_add(bd, drag_border->evas);
8118                              if (!o)
8119                                {
8120      /* FIXME: fallback icon for drag */
8121                                    o = evas_object_rectangle_add(drag_border->evas);
8122                                    evas_object_color_set(o, 255, 255, 255, 255);
8123                                }
8124                              e_drag_object_set(drag_border, o);
8125
8126                              e_drag_resize(drag_border, w, h);
8127                              e_drag_start(drag_border, bd->drag.x, bd->drag.y);
8128                           }
8129                         bd->drag.start = 0;
8130                     }
8131                }
8132           }
8133         evas_event_feed_mouse_move(bd->bg_evas, ev->x, ev->y, ev->timestamp, NULL);
8134      }
8135    return ECORE_CALLBACK_PASS_ON;
8136 }
8137
8138 static Eina_Bool
8139 _e_border_cb_grab_replay(void *data __UNUSED__,
8140                          int        type,
8141                          void      *event)
8142 {
8143    Ecore_Event_Mouse_Button *ev;
8144
8145    if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
8146    ev = event;
8147    if ((e_config->pass_click_on)
8148        || (e_config->always_click_to_raise) // this works even if not on click-to-focus
8149        || (e_config->always_click_to_focus) // this works even if not on click-to-focus
8150       )
8151      {
8152         E_Border *bd;
8153
8154         bd = e_border_find_by_window(ev->event_window);
8155         if (bd)
8156           {
8157              if (bd->cur_mouse_action)
8158                return ECORE_CALLBACK_DONE;
8159              if (ev->event_window == bd->win)
8160                {
8161                   if (!e_bindings_mouse_down_find(E_BINDING_CONTEXT_WINDOW,
8162                                                   E_OBJECT(bd), ev, NULL))
8163                     return ECORE_CALLBACK_PASS_ON;
8164                }
8165           }
8166      }
8167    return ECORE_CALLBACK_DONE;
8168 }
8169
8170 static void
8171 _e_border_cb_drag_finished(E_Drag     *drag,
8172                            int dropped __UNUSED__)
8173 {
8174    E_Border *bd;
8175
8176    bd = drag->data;
8177    e_object_unref(E_OBJECT(bd));
8178    drag_border = NULL;
8179 }
8180
8181 #ifdef _F_USE_DESK_WINDOW_PROFILE_
8182 static Eina_Bool
8183 _e_border_cb_desk_window_profile_change(void *data  __UNUSED__,
8184                                         int ev_type __UNUSED__,
8185                                         void       *ev)
8186 {
8187    E_Event_Desk_Window_Profile_Change *e;
8188    Eina_List *l;
8189    E_Border *bd;
8190
8191    e = ev;
8192    EINA_LIST_FOREACH(borders, l, bd)
8193      {
8194         if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
8195           {
8196              bd->client.e.fetch.profile_list = 1;
8197              bd->changed = 1;
8198           }
8199      }
8200    return ECORE_CALLBACK_PASS_ON;
8201 }
8202 #endif
8203
8204 #ifdef _F_ZONE_WINDOW_ROTATION_
8205 static Eina_Bool
8206 _e_border_cb_zone_rotation_change_begin(void *data  __UNUSED__,
8207                                         int ev_type __UNUSED__,
8208                                         void       *ev)
8209 {
8210    E_Event_Zone_Rotation_Change_Begin *e = ev;
8211
8212    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8213    if ((!e) || (!e->zone)) return ECORE_CALLBACK_PASS_ON;
8214
8215    if (!_e_border_rotation_zone_set(e->zone))
8216      {
8217         /* there is no border which supports window manager rotation */
8218         e_zone_rotation_update_cancel(e->zone);
8219      }
8220    return ECORE_CALLBACK_PASS_ON;
8221 }
8222
8223 static void
8224 _e_border_cb_rotation_sync_job(void *data)
8225 {
8226    E_Zone *zone = data;
8227    Eina_List *l;
8228    E_Border_Rotation_Info *info = NULL;
8229
8230    ELBF(ELBT_ROT, 0, zone->id, "DO ROTATION SYNC_JOB rot.list:%p(%d) wait_prepare_done:%d zone_block_count:%d",
8231         rot.list, eina_list_count(rot.list), rot.wait_prepare_done, zone->rot.block_count);
8232    if (rot.list)
8233      {
8234         EINA_LIST_FOREACH(rot.list, l, info)
8235            _e_border_hook_call(E_BORDER_HOOK_ROTATION_LIST_ADD, info->bd);
8236
8237         ELBF(ELBT_ROT, 0, zone->id, "SYNC_JOB list(%d) wait_prepare_done:%d zone_block_count:%d",
8238              eina_list_count(rot.list), rot.wait_prepare_done, zone->rot.block_count);
8239
8240         if (!rot.wait_prepare_done)
8241           {
8242              _e_border_rotation_change_request(zone);
8243           }
8244      }
8245
8246    // clear job
8247    if (rot.sync_job)
8248      {
8249         ELB(ELBT_ROT, "DEL SYNC_JOB", zone->id);
8250         ecore_job_del(rot.sync_job);
8251         rot.sync_job = NULL;
8252      }
8253 }
8254
8255 static void
8256 _e_border_cb_rotation_async_job(void *data)
8257 {
8258    E_Zone *zone = data;
8259
8260    if (rot.list) goto end;
8261
8262    ELB(ELBT_ROT, "FLUSH ASYNC LIST TO ROT_CHANGE_REQ", zone->id);
8263
8264    if (!rot.wait_prepare_done)
8265      {
8266         _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8267         rot.async_list = NULL;
8268      }
8269
8270 end:
8271    // clear async job
8272    if (rot.async_job)
8273      {
8274         ELB(ELBT_ROT, "DEL ASYNC_JOB", zone->id);
8275         ecore_job_del(rot.async_job);
8276         rot.async_job = NULL;
8277      }
8278 }
8279
8280 static Eina_Bool
8281 _e_border_rotation_change_prepare_timeout(void *data)
8282 {
8283    E_Zone *zone = data;
8284    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8285
8286    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE_PREPARE", 0);
8287
8288    if ((zone) && (rot.wait_prepare_done))
8289      {
8290         if (rot.list)
8291           {
8292              _e_border_rotation_change_request(zone);
8293              if (rot.prepare_timer)
8294                ecore_timer_del(rot.prepare_timer);
8295              rot.prepare_timer = NULL;
8296              rot.wait_prepare_done = EINA_FALSE;
8297           }
8298      }
8299    return ECORE_CALLBACK_CANCEL;
8300 }
8301
8302 static void
8303 _e_border_rotation_change_request(E_Zone *zone)
8304 {
8305    if (!e_config->wm_win_rotation) return;
8306    if (!rot.list) return;
8307    if (eina_list_count(rot.list) <= 0) return;
8308    /* pending rotation problem occurred while launching app by the tray */
8309    //if (zone->rot.block_count) return;
8310
8311    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8312    rot.prepare_timer = NULL;
8313    rot.wait_prepare_done = EINA_FALSE;
8314
8315    _e_border_rotation_list_flush(rot.list, EINA_FALSE);
8316
8317    if (rot.done_timer)
8318      ecore_timer_del(rot.done_timer);
8319    ELB(ELBT_ROT, "ADD TIMEOUT ROT_DONE", zone->id);
8320    rot.done_timer = ecore_timer_add(5.0f,
8321                                     _e_border_rotation_change_done_timeout,
8322                                     NULL);
8323 }
8324
8325 static void
8326 _e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush)
8327 {
8328    Eina_List *l;
8329    E_Border_Rotation_Info *info =NULL;
8330    int x, y, w, h;
8331
8332    EINA_LIST_FOREACH (list, l, info)
8333      {
8334         if (!info->bd) continue;
8335         if ((info->bd->client.e.state.rot.wait_for_done) &&
8336             (info->bd->client.e.state.rot.wait_done_ang == info->ang)) continue;
8337
8338         _e_border_event_border_rotation_change_begin_send(info->bd);
8339
8340         /* resize border */
8341         info->win_resize = _e_border_rotation_pre_resize(info->bd, info->ang, &x, &y, &w, &h);
8342         info->bd->client.e.state.rot.pending_change_request = info->win_resize;
8343
8344         info->x = x; info->y = y;
8345         info->w = w; info->h = h;
8346
8347         ELBF(ELBT_ROT, 1, info->bd->client.win,
8348              "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
8349              info->ang, info->win_resize, info->w, info->h);
8350
8351 #ifdef _F_USE_DLOG_
8352              SECURE_SLOGD("[ROTATION] SEND PREP_ROT, win:0x%08x a%d resize%d %dx%d",
8353                           info->bd->client.win, info->ang, info->win_resize,
8354                           info->w, info->h);
8355 #endif
8356
8357         ecore_x_e_window_rotation_change_prepare_send
8358            (info->bd->client.win, info->ang,
8359             info->win_resize, info->w, info->h);
8360
8361         if (!info->bd->client.e.state.rot.pending_change_request)
8362           {
8363              ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
8364 #ifdef _F_USE_DLOG_
8365              SECURE_SLOGD("[ROTATION] SEND REQ_ROT, win:0x%08x, rot:%d",
8366                           info->bd->client.win, info->ang);
8367 #endif
8368              ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
8369                                                            info->ang);
8370              info->bd->client.e.state.rot.wait_for_done = 1;
8371              info->bd->client.e.state.rot.wait_done_ang = info->ang;
8372           }
8373      }
8374
8375    if (flush)
8376      {
8377         EINA_LIST_FREE(list, info)
8378            E_FREE(info);
8379      }
8380 }
8381
8382 EAPI void
8383 e_border_rotation_list_clear(E_Zone *zone, Eina_Bool send_request)
8384 {
8385    E_Border_Rotation_Info *info = NULL;
8386
8387    if (send_request) _e_border_rotation_change_request(zone);
8388    else
8389      {
8390         EINA_LIST_FREE(rot.list, info)
8391            E_FREE(info);
8392         rot.list = NULL;
8393      }
8394 }
8395
8396 static void
8397 _e_border_rotation_list_remove(E_Border *bd)
8398 {
8399    Eina_List *l = NULL;
8400    E_Border_Rotation_Info *info = NULL;
8401    E_Event_Border_Rotation_Change_End *ev = NULL;
8402    Eina_Bool found = EINA_FALSE;
8403
8404    if (!e_config->wm_win_rotation) return;
8405
8406    EINA_LIST_FOREACH(rot.list, l, info)
8407      {
8408         if (info->bd == bd)
8409           {
8410              rot.list = eina_list_remove(rot.list, info);
8411              E_FREE(info);
8412              found = EINA_TRUE;
8413           }
8414      }
8415
8416    if (bd->client.e.state.rot.wait_for_done)
8417      {
8418         bd->client.e.state.rot.wait_for_done = 0;
8419
8420         /* if we make the border event in the _e_border_free function,
8421          * then we may meet a crash problem, only work this at least e_border_hide.
8422          */
8423         if (!e_object_is_del(E_OBJECT(bd)))
8424           {
8425              ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
8426              if (ev)
8427                {
8428                   ev->border = bd;
8429                   e_object_ref(E_OBJECT(bd));
8430                   ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_END,
8431                                   ev,
8432                                   _e_border_event_border_rotation_change_end_free,
8433                                   NULL);
8434                }
8435           }
8436
8437         if ((found) &&
8438             (eina_list_count(rot.list) == 0))
8439           {
8440              _e_border_rotation_change_done();
8441           }
8442      }
8443 }
8444
8445 static Eina_Bool
8446 _e_border_rotation_change_done_timeout(void *data __UNUSED__)
8447 {
8448    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8449    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE", 0);
8450    _e_border_rotation_change_done();
8451    return ECORE_CALLBACK_CANCEL;
8452 }
8453
8454 static void
8455 _e_border_rotation_change_done(void)
8456 {
8457    E_Manager *m = NULL;
8458    E_Border_Rotation_Info *info = NULL;
8459
8460    if (!e_config->wm_win_rotation) return;
8461
8462    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8463    rot.prepare_timer = NULL;
8464
8465    rot.wait_prepare_done = EINA_FALSE;
8466
8467    if (rot.done_timer) ecore_timer_del(rot.done_timer);
8468    rot.done_timer = NULL;
8469
8470    EINA_LIST_FREE(rot.list, info)
8471      {
8472         if (info->bd)
8473           {
8474              ELB(ELBT_ROT, "TIMEOUT ROT_DONE", info->bd->client.win);
8475              if (info->bd->client.e.state.rot.pending_show)
8476                {
8477                   ELB(ELBT_ROT, "SHOW PEND(TIMEOUT)", info->bd->client.win);
8478                   e_border_show(info->bd);
8479 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
8480                   if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
8481                     _e_border_check_stack(info->bd);
8482 #endif
8483                   info->bd->client.e.state.rot.pending_show = 0;
8484                }
8485              info->bd->client.e.state.rot.wait_for_done = 0;
8486           }
8487         E_FREE(info);
8488      }
8489
8490    _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8491
8492    rot.list = NULL;
8493    rot.async_list = NULL;
8494
8495    m = e_manager_current_get();
8496    e_manager_comp_screen_unlock(m);
8497    e_zone_rotation_update_done(e_util_zone_current_get(m));
8498 }
8499
8500 static int
8501 _prev_angle_get(Ecore_X_Window win)
8502 {
8503    int ret, count = 0, ang = -1;
8504    unsigned char* data = NULL;
8505
8506    ret = ecore_x_window_prop_property_get
8507       (win, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
8508       ECORE_X_ATOM_CARDINAL, 32, &data, &count);
8509
8510    if ((ret) && (data) && (count))
8511      ang = ((int *)data)[0];
8512    if (data) free(data);
8513    return ang;
8514 }
8515
8516 /* get proper rotation value using preferred rotation and list of available rotations */
8517 static int
8518 _e_border_rotation_get(E_Border *bd,
8519                        int       base_ang)
8520 {
8521    int ang = -1;
8522    int current_ang = bd->client.e.state.rot.curr;
8523    unsigned int i;
8524    Eina_Bool found = EINA_FALSE;
8525    Eina_Bool found_curr_ang = EINA_FALSE;
8526
8527    if (!e_config->wm_win_rotation) return ang;
8528    if (!bd->client.e.state.rot.app_set) return ang;
8529
8530    if (bd->client.e.state.rot.preferred_rot != -1)
8531      {
8532         ang = bd->client.e.state.rot.preferred_rot;
8533         ELBF(ELBT_ROT, 0, bd->client.win, "ang:%d base_ang:%d", ang, base_ang);
8534      }
8535    else if ((bd->client.e.state.rot.available_rots) &&
8536             (bd->client.e.state.rot.count))
8537      {
8538         for (i = 0; i < bd->client.e.state.rot.count; i++)
8539           {
8540              if (bd->client.e.state.rot.available_rots[i] == base_ang)
8541                {
8542                   ang = base_ang;
8543                   found = EINA_TRUE;
8544                   break;
8545                }
8546              if (bd->client.e.state.rot.available_rots[i] == current_ang)
8547                found_curr_ang = EINA_TRUE;
8548           }
8549
8550         /* do nothing. this window wants to maintain current state.
8551          * for example, window's available_rots: 0, 90, 270,
8552          * current zone rotation request: 180. the WM does nothing
8553          * for this window.
8554          */
8555         if (!found)
8556           {
8557              if ((bd->client.e.state.rot.curr != -1) && (found_curr_ang))
8558                ang = bd->client.e.state.rot.curr;
8559              else
8560                ang = bd->client.e.state.rot.available_rots[0];
8561           }
8562      }
8563    else
8564      {
8565         /* In this case, border doesn't have a list of
8566          * available rotations, thus WM should request
8567          * rotation with '0' degree to the application.
8568          */
8569         ang = 0;
8570      }
8571
8572    return ang;
8573 }
8574
8575 static int
8576 _e_border_rotation_angle_get(E_Border *bd)
8577 {
8578    E_Zone *zone = bd->zone;
8579    int will_ang = 0;
8580    int _ang = 0;
8581    int ret = -1;
8582
8583    if (!e_config->wm_win_rotation) return ret;
8584    if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) return ret;
8585
8586    ELB(ELBT_ROT, "CHECK ROT", bd->client.win);
8587
8588    // the window with "ECORE_X_WINDOW_TYPE_NORMAL" type
8589    // should follow the state of rotation of zone.
8590    if ((bd->parent) &&
8591        (bd->parent->visible) &&
8592        (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL))
8593      will_ang = bd->parent->client.e.state.rot.curr;
8594    else will_ang = zone->rot.curr;
8595
8596    if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
8597      {
8598         ELBF(ELBT_ROT, 1, bd->client.win,
8599              "%s->parent:0x%08x (support:%d app_set:%d ang:%d)",
8600              (rot.vkbd == bd) ? "vkbd" : "prediction",
8601              bd->parent ? bd->parent->client.win : 0,
8602              bd->parent ? bd->parent->client.e.state.rot.support : -1,
8603              bd->parent ? bd->parent->client.e.state.rot.app_set : -1,
8604              bd->parent ? bd->parent->client.e.state.rot.curr : -1);
8605
8606         if (bd->parent)
8607           {
8608              will_ang = bd->parent->client.e.state.rot.curr;
8609              if ((!bd->parent->client.e.state.rot.support) &&
8610                  (!bd->parent->client.e.state.rot.app_set))
8611                {
8612                   will_ang = 0;
8613                }
8614           }
8615      }
8616
8617    if ((!bd->client.e.state.rot.app_set) &&
8618        (!bd->client.e.state.rot.support))
8619      {
8620         /* hack for magnifier and keyboard popup */
8621         if ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER) ||
8622             (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP))
8623           {
8624              ELB(ELBT_BD, "MAG", bd->client.win);
8625              will_ang = 0;
8626              if ((rot.vkbd) && (rot.vkbd->visible))
8627                will_ang = rot.vkbd->client.e.state.rot.curr;
8628           }
8629      }
8630
8631    if (bd->client.e.state.rot.app_set)
8632      {
8633         /* utility type window should be rotated according to
8634          * rotation of the transient_for window.
8635          */
8636         if ((bd->parent) &&
8637             (bd->parent->visible) &&
8638             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
8639           {
8640              will_ang = bd->parent->client.e.state.rot.curr;
8641              if ((!bd->parent->client.e.state.rot.support) &&
8642                  (!bd->parent->client.e.state.rot.app_set))
8643                {
8644                   /* if transient_for window doesn't support rotation feature,
8645                    * then this window should't be rotated.
8646                    * TODO: need to check whether window supports '0' degree or not.
8647                    */
8648                   will_ang = 0;
8649                   ELBF(ELBT_ROT, 0, bd->client.win,
8650                        "GET ROT ang:%d Transient_For:0x%08x Not support rot",
8651                        will_ang, bd->parent->client.win);
8652                }
8653              else
8654                {
8655                   will_ang = _e_border_rotation_get(bd->parent, will_ang);
8656                   ELBF(ELBT_ROT, 0, bd->client.win,
8657                        "GET ROT ang:%d Transient_For:0x%08x",
8658                        will_ang, bd->parent->client.win);
8659                }
8660           }
8661         else
8662           {
8663              will_ang = _e_border_rotation_get(bd, will_ang);
8664              ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d",
8665                   will_ang, bd->parent ? bd->parent->client.win : 0,
8666                   bd->client.netwm.type);
8667           }
8668      }
8669
8670    if (bd->new_client)
8671      {
8672         _ang = _prev_angle_get(bd->client.win);
8673         if (_ang != -1)
8674           bd->client.e.state.rot.curr = _ang;
8675         ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang);
8676      }
8677
8678    if (bd->client.e.state.rot.curr != will_ang)
8679      ret = will_ang;
8680
8681    return ret;
8682 }
8683
8684
8685 static Eina_Bool
8686 _e_border_rotation_zone_set(E_Zone *zone)
8687 {
8688    E_Border_List *l = NULL;
8689    E_Border *bd = NULL;
8690    Eina_Bool ret = EINA_FALSE;
8691
8692    if (!e_config->wm_win_rotation) return EINA_FALSE;
8693
8694    l = e_container_border_list_last(zone->container);
8695    if (!l) return ret;
8696
8697    /* step 1. make the list needs to be rotated. */
8698    while ((bd = e_container_border_list_prev(l)))
8699      {
8700         if (!bd) continue;
8701
8702         // if this window has parent and window type isn't "ECORE_X_WINDOW_TYPE_NORMAL",
8703         // it will be rotated when parent do rotate itself.
8704         // so skip here.
8705         if ((bd->parent) &&
8706             (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL)) continue;
8707
8708         // default type is "E_BORDER_ROTATION_TYPE_NORMAL",
8709         // but it can be changed to "E_BORDER_ROTATION_TYPE_DEPENDENT" by illume according to its policy.
8710         // if it's not normal type window, will be rotated by illume.
8711         // so skip here.
8712         if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue;
8713
8714         if ((!bd->visible) ||
8715             (!E_INTERSECTS(bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h,
8716                            bd->x, bd->y, bd->w, bd->h))) continue;
8717
8718         if (_e_border_rotatable_check(bd, zone->rot.curr))
8719           {
8720              ELBF(ELBT_ROT, 0, bd->client.win, "ROT_SET(main) curr:%d != TOBE:%d",
8721                   bd->client.e.state.rot.curr, zone->rot.curr);
8722
8723              ret = e_border_rotation_set(bd, zone->rot.curr);
8724           }
8725      }
8726    if (l) e_container_border_list_free(l);
8727
8728    return ret;
8729 }
8730
8731 static Eina_Bool
8732 _e_border_rotation_set_internal(E_Border *bd, int rotation, Eina_Bool *pending)
8733 {
8734    E_Zone *zone = bd->zone;
8735    E_Border_Rotation_Info *info = NULL;
8736    Eina_List *list, *l;
8737    E_Border *child;
8738
8739    if (rotation < 0) return EINA_FALSE;
8740    if (pending) *pending = EINA_FALSE;
8741
8742    /* step 1. check if rotation */
8743    if (!_e_border_rotatable_check(bd, rotation)) return EINA_FALSE;
8744
8745    /* step 2. add to async/sync list */
8746    if ((!zone->rot.block_count) &&
8747        (!bd->client.e.state.deiconify_approve.pending_bd) &&
8748        ((!bd->visible) ||
8749         (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))))
8750      {
8751         // send rotation change request later.
8752         // and no need to wait message of rotation done.
8753
8754         // async list add
8755         info = E_NEW(E_Border_Rotation_Info, 1);
8756         if (!info) return EINA_FALSE;
8757         ELB(ELBT_ROT, "ADD ASYNC LIST", 0);
8758         info->bd = bd;
8759         info->ang = rotation;
8760         rot.async_list = eina_list_append(rot.async_list, info);
8761
8762         // add job for sending event.
8763         if (!rot.async_job)
8764           {
8765              ELB(ELBT_ROT, "ADD ASYNC_JOB", bd->client.win);
8766              rot.async_job = ecore_job_add(_e_border_cb_rotation_async_job, zone);
8767           }
8768      }
8769    else
8770      {
8771         // sync list add
8772         info = E_NEW(E_Border_Rotation_Info, 1);
8773         if (!info) return EINA_FALSE;
8774         ELB(ELBT_ROT, "ADD SYNC LIST", 0);
8775         info->bd = bd;
8776         info->ang = rotation;
8777         rot.list = eina_list_append(rot.list, info);
8778
8779         // add job for sending event.
8780         if (!rot.sync_job)
8781           {
8782              ELB(ELBT_ROT, "ADD SYNC_JOB", bd->client.win);
8783              rot.sync_job = ecore_job_add(_e_border_cb_rotation_sync_job, zone);
8784           }
8785
8786         // if there is windows over 2 that has to be rotated or is existed window needs resizing,
8787         // lock the screen.
8788         // but, DO NOT lock the screen when rotation block state.
8789         if ((!zone->rot.block_count) &&
8790             ((eina_list_count(rot.list) == 2)))
8791           e_manager_comp_screen_lock(e_manager_current_get());
8792      }
8793
8794    if (pending) *pending = EINA_TRUE;
8795
8796    /* step 3. search rotatable window in this window's child */
8797    list = _e_border_sub_borders_new(bd);
8798    EINA_LIST_FOREACH(list, l, child)
8799      {
8800         // the window which type is "ECORE_X_WINDOW_TYPE_NORMAL" will be rotated itself.
8801         // it shouldn't be rotated by rotation state of parent window.
8802         if (child->client.netwm.type == ECORE_X_WINDOW_TYPE_NORMAL) continue;
8803         if (_e_border_rotatable_check(child, rotation))
8804           {
8805              ELBF(ELBT_ROT, 0, child->client.win, "ROT_SET(child) curr:%d != TOBE:%d",
8806                   bd->client.e.state.rot.curr, rotation);
8807              e_border_rotation_set(child, rotation);
8808           }
8809      }
8810
8811    /* step 4. if there is vkbd window, send message to prepare rotation */
8812    if (_e_border_is_vkbd(bd))
8813      {
8814         ELB(ELBT_ROT, "PENDING ROT_REQ UNTIL GET PREP_DONE", rot.vkbd_ctrl_win);
8815         if (rot.prepare_timer)
8816           ecore_timer_del(rot.prepare_timer);
8817         rot.prepare_timer = NULL;
8818
8819         if (rot.done_timer)
8820           ecore_timer_del(rot.done_timer);
8821         rot.done_timer = NULL;
8822
8823         ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win);
8824         ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8825                                                       zone->rot.curr,
8826                                                       EINA_FALSE, 1, 1);
8827         rot.prepare_timer = ecore_timer_add(4.0f,
8828                                             _e_border_rotation_change_prepare_timeout,
8829                                             NULL);
8830
8831         rot.wait_prepare_done = EINA_TRUE;
8832      }
8833
8834    bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8835    bd->client.e.state.rot.curr = rotation;
8836
8837    return EINA_TRUE;
8838 }
8839
8840 // check if border is rotatable in ang.
8841 static Eina_Bool
8842 _e_border_rotatable_check(E_Border *bd, int ang)
8843 {
8844    Eina_Bool ret = EINA_FALSE;
8845
8846    if (!bd) return ret;
8847    if (ang < 0) return ret;
8848    if ((!bd->client.e.state.rot.support) && (!bd->client.e.state.rot.app_set)) return ret;
8849    if (e_object_is_del(E_OBJECT(bd))) return ret;
8850
8851    // same with current angle of window, then false return.
8852    if (ang == bd->client.e.state.rot.curr) return ret;
8853
8854    /* basically WM allows only fullscreen window to rotate */
8855    if (bd->client.e.state.rot.preferred_rot == -1)
8856      {
8857         unsigned int i;
8858
8859         if (bd->client.e.state.rot.app_set)
8860           {
8861              if (bd->client.e.state.rot.available_rots &&
8862                  bd->client.e.state.rot.count)
8863                {
8864                   Eina_Bool found = EINA_FALSE;
8865                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8866                     {
8867                        if (bd->client.e.state.rot.available_rots[i] == ang)
8868                          {
8869                             found = EINA_TRUE;
8870                          }
8871                     }
8872                   if (found) ret = EINA_TRUE;
8873                }
8874           }
8875         else
8876           {
8877              ELB(ELBT_ROT, "DO ROT", 0);
8878              ret = EINA_TRUE;
8879           }
8880      }
8881    // if it has preferred rotation angle,
8882    // it will be rotated at border's evaluation time.
8883    // so skip it.
8884    else if (bd->client.e.state.rot.preferred_rot == ang) ret = EINA_TRUE;
8885
8886    return ret;
8887 }
8888
8889 /* check whether virtual keyboard is visible on the zone */
8890 static Eina_Bool
8891 _e_border_is_vkbd(E_Border *bd)
8892 {
8893    if (!e_config->wm_win_rotation) return EINA_FALSE;
8894
8895    if ((rot.vkbd_ctrl_win) &&
8896        (rot.vkbd == bd) &&
8897        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8898        (rot.vkbd->zone == bd->zone) &&
8899        (E_INTERSECTS(bd->zone->x, bd->zone->y,
8900                      bd->zone->w, bd->zone->h,
8901                      rot.vkbd->x, rot.vkbd->y,
8902                      rot.vkbd->w, rot.vkbd->h)))
8903      {
8904         return EINA_TRUE;
8905      }
8906    return EINA_FALSE;
8907 }
8908
8909 static Eina_Bool
8910 _e_border_rotation_change_floating_pos(E_Border *bd, int *x, int *y)
8911 {
8912    int new_x, new_y;
8913    int min_title_width=96;
8914
8915    if (!bd) return EINA_FALSE;
8916    if (!x || !y) return EINA_FALSE;
8917
8918    new_x = bd->x;
8919    new_y = bd->y;
8920
8921    // Portrait -> Landscape,  x= pre_x*2, y=pre_y/2
8922    // Landscape -> Portrait,  x= pre_x/2, y=pre_y*2
8923    // guaranteeing the minimum size of titlebar shown, min_title_width
8924    // so user can initiate drag&drop action after rotation changed.
8925    if (bd->client.e.state.rot.curr == 0)
8926      {
8927         if (bd->client.e.state.rot.prev == 90)
8928           {
8929              new_x = (bd->zone->h - bd->h - bd->y) / 2;
8930              new_y = 2 * bd->x;
8931           }
8932         else if (bd->client.e.state.rot.prev == 270)
8933           {
8934              new_x = bd->y / 2;
8935              new_y = (bd->zone->w - bd->w - bd->x) * 2;
8936           }
8937         else if (bd->client.e.state.rot.prev == 180)
8938           {
8939              new_x = bd->zone->w - bd->x - bd->w;
8940              new_y = bd->zone->h - bd->y - bd->h;
8941           }
8942
8943         if(new_x + bd->w < min_title_width)
8944           {
8945              new_x = min_title_width - bd->w;
8946           }
8947         else if(new_x > bd->zone->w - min_title_width)
8948           {
8949              new_x = bd->zone->w - min_title_width;
8950           }
8951      }
8952    else if (bd->client.e.state.rot.curr == 90)
8953      {
8954         if (bd->client.e.state.rot.prev == 0)
8955           {
8956              new_x = bd->y / 2;
8957              new_y = bd->zone->h - (2 * bd->x) - bd->w;
8958           }
8959         else if (bd->client.e.state.rot.prev == 270)
8960           {
8961              new_x = bd->zone->w - bd->x - bd->w;
8962              new_y = bd->zone->h - bd->y - bd->h;
8963           }
8964         else if (bd->client.e.state.rot.prev == 180)
8965           {
8966              new_x = (bd->zone->h - bd->y - bd->h) / 2;
8967              new_y = bd->zone->h - (2 * (bd->zone->w - bd->x - bd->w)) - bd->w;
8968           }
8969
8970         if(new_y > bd->zone->h - min_title_width)
8971           {
8972              new_y = bd->zone->h - min_title_width;
8973           }
8974         else if(new_y < min_title_width - bd->w)
8975           {
8976              new_y = min_title_width - bd->w;
8977           }
8978      }
8979    else if (bd->client.e.state.rot.curr == 270)
8980      {
8981         if (bd->client.e.state.rot.prev == 0)
8982           {
8983              new_x = bd->zone->w - bd->h - (bd->y / 2);
8984              new_y = bd->x * 2;
8985           }
8986         else if (bd->client.e.state.rot.prev == 90)
8987           {
8988              new_x = bd->zone->w - bd->x - bd->w;
8989              new_y = bd->zone->h - bd->y - bd->h;
8990           }
8991         else if (bd->client.e.state.rot.prev == 180)
8992           {
8993              new_x = bd->zone->w - bd->x - bd->w;
8994              new_y = bd->zone->h - bd->y - bd->h;
8995
8996              new_x = bd->zone->w - bd->h - ((bd->zone->h - bd->y - bd->h) / 2);
8997              new_y = (bd->zone->w - bd->x - bd->w) * 2;
8998           }
8999
9000         if(new_y >  bd->zone->h - min_title_width)
9001           {
9002              new_y = bd->zone->h - min_title_width;
9003           }
9004         else if( new_y + bd->w < min_title_width)
9005           {
9006              new_y = min_title_width - bd->w ;
9007           }
9008      }
9009    else if (bd->client.e.state.rot.curr == 180)
9010      {
9011         if (bd->client.e.state.rot.prev == 0)
9012           {
9013              new_x = bd->zone->w - bd->x - bd->w;
9014              new_y = bd->zone->h - bd->y - bd->h;
9015           }
9016         else if (bd->client.e.state.rot.prev == 90)
9017           {
9018              new_x = bd->zone->w - ((bd->zone->h - bd->h - bd->y) / 2) - bd->h;
9019              new_y = bd->zone->h - (2 * bd->x) - bd->w;
9020           }
9021         else if (bd->client.e.state.rot.prev == 270)
9022           {
9023              new_x = bd->zone->w - (bd->y / 2) - bd->h;
9024              new_y = bd->zone->h - ((bd->zone->w - bd->w - bd->x) * 2) - bd->w;
9025           }
9026
9027         if(new_x + bd->w < min_title_width)
9028           {
9029              new_x = min_title_width - bd->w;
9030           }
9031         else if(new_x > bd->zone->w - min_title_width)
9032           {
9033              new_x = bd->zone->w - min_title_width;
9034           }
9035      }
9036
9037    ELBF(ELBT_ROT, 0, bd->client.win,
9038         "Floating Mode. ANGLE (%d->%d), POS (%d,%d) -> (%d,%d)",
9039         bd->client.e.state.rot.prev, bd->client.e.state.rot.curr,
9040         bd->x, bd->y, new_x, new_y);
9041
9042    if ((new_x == *x) &&
9043        (new_y == *y))
9044      {
9045         return EINA_FALSE;
9046      }
9047
9048    *x = new_x;
9049    *y = new_y;
9050
9051    return EINA_TRUE;
9052 }
9053
9054 #define SIZE_EQUAL_TO_ZONE(a, z) \
9055    ((((a)->w) == ((z)->w)) &&    \
9056     (((a)->h) == ((z)->h)))
9057 static Eina_Bool
9058 _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h)
9059 {
9060    E_Zone *zone = bd->zone;
9061    int rot_dif;
9062    int _x, _y, _w, _h;
9063    Eina_Bool move = EINA_FALSE;
9064    Eina_Bool hint = EINA_FALSE;
9065    Eina_Bool resize = EINA_FALSE;
9066
9067    if (x) *x = bd->x;
9068    if (y) *y = bd->y;
9069    if (w) *w = bd->w;
9070    if (h) *h = bd->h;
9071
9072    if (SIZE_EQUAL_TO_ZONE(bd, zone)) return resize;
9073
9074    ELB(ELBT_ROT, "SIZE DIFF WITH ZONE", 0);
9075    ELBF(ELBT_ROT, 0, bd->client.win, "ORIGIN_SIZE name:%s (%d,%d) %dx%d",
9076         bd->client.icccm.name, bd->x, bd->y, bd->w, bd->h);
9077
9078    hint = _e_border_rotation_geom_get(bd, bd->zone, rotation,
9079                                       &_x, &_y, &_w, &_h, &move);
9080    if (hint)
9081      {
9082         if (((move) && ((bd->x !=_x) || (bd->y !=_y))) ||
9083             (bd->w != _w) || (bd->h != _h))
9084           {
9085              resize = EINA_TRUE;
9086              _e_border_move_resize_internal(bd, _x, _y, _w, _h, EINA_TRUE, move);
9087              ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d resize:%d",
9088                   bd->client.icccm.name, _x, _y, _w, _h, resize);
9089           }
9090      }
9091    else
9092      {
9093         _x = bd->x; _y = bd->y;
9094         _w = bd->w; _h = bd->h;
9095
9096         if (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)
9097           move = _e_border_rotation_change_floating_pos(bd, &_x, &_y);
9098         else
9099           move = EINA_FALSE;
9100
9101         rot_dif = bd->client.e.state.rot.prev - rotation;
9102         if (rot_dif < 0) rot_dif = -rot_dif;
9103         if (rot_dif != 180)
9104           {
9105              if (_w != _h)
9106                {
9107                   _w = bd->h;
9108                   _h = bd->w;
9109                   resize = EINA_TRUE;
9110
9111                   _e_border_move_resize_internal(bd, _x, _y, _w, _h,
9112                                                  EINA_TRUE, EINA_TRUE);
9113                   ELBF(ELBT_ROT, 0, bd->client.win, "MANUAL_RESIZE name:%s (%d,%d) %dx%d",
9114                        bd->client.icccm.name, _x, _y, _w, _h);
9115
9116                }
9117           }
9118
9119         if (!resize && move)
9120           _e_border_move_internal(bd, _x, _y, EINA_TRUE);
9121      }
9122
9123    if (resize)
9124      {
9125         if (x) *x = _x;
9126         if (y) *y = _y;
9127         if (w) *w = _w;
9128         if (h) *h = _h;
9129      }
9130
9131    return resize;
9132 }
9133
9134 static Eina_Bool
9135 _e_border_cb_window_configure(void *data    __UNUSED__,
9136                               int   ev_type __UNUSED__,
9137                               void         *ev)
9138 {
9139    Ecore_X_Event_Window_Configure *e = ev;
9140    E_Border_Rotation_Info *info = NULL;
9141    Eina_List *l;
9142    Eina_Bool found = EINA_FALSE;
9143
9144    if (!e) return ECORE_CALLBACK_PASS_ON;
9145    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
9146
9147    E_Border *bd = e_border_find_by_client_window(e->win);
9148    if (!bd) return ECORE_CALLBACK_PASS_ON;
9149
9150    if (bd->client.e.state.rot.pending_change_request)
9151      {
9152         if ((e->w == bd->w) && (e->h == bd->h))
9153           {
9154              ELB(ELBT_BD, "GET CONFIGURE_NOTI (ROTATION)", bd->client.win);
9155              bd->client.e.state.rot.pending_change_request = 0;
9156
9157              if ((bd->client.e.state.rot.wait_for_done) &&
9158                  (bd->client.e.state.rot.wait_done_ang == bd->client.e.state.rot.curr)) goto end;
9159
9160              EINA_LIST_FOREACH(rot.list, l, info)
9161                 if (info->bd == bd) found = EINA_TRUE;
9162              // send request message if it's async rotation window,
9163              // even if wait prepare done.
9164              if ((found) && (rot.wait_prepare_done)) goto end;
9165
9166              ELBF(ELBT_ROT, 0, bd->client.win,
9167                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
9168                   bd->client.e.state.rot.curr,
9169                   bd->w, bd->h);
9170 #ifdef _F_USE_DLOG_
9171              SECURE_SLOGD("[ROTATION] SEND REQ_ROT(CONFIGURE_NOTI), win:0x%08x, rot:%d",
9172                           bd->client.win, bd->client.e.state.rot.curr);
9173 #endif
9174              ecore_x_e_window_rotation_change_request_send(bd->client.win,
9175                                                            bd->client.e.state.rot.curr);
9176              bd->client.e.state.rot.wait_for_done = 1;
9177              bd->client.e.state.rot.wait_done_ang = bd->client.e.state.rot.curr;
9178           }
9179      }
9180
9181 end:
9182    return ECORE_CALLBACK_PASS_ON;
9183 }
9184
9185 static Eina_Bool
9186 _e_border_rotation_geom_get(E_Border  *bd,
9187                             E_Zone    *zone,
9188                             int        ang,
9189                             int       *x,
9190                             int       *y,
9191                             int       *w,
9192                             int       *h,
9193                             Eina_Bool *move)
9194 {
9195    if (!e_config->wm_win_rotation) return EINA_FALSE;
9196
9197    Eina_Bool res = EINA_FALSE;
9198    Eina_Bool _move = EINA_TRUE;
9199    int _x = bd->x;
9200    int _y = bd->y;
9201    int _w = bd->w;
9202    int _h = bd->h;
9203
9204    if (x) *x = bd->x;
9205    if (y) *y = bd->y;
9206    if (w) *w = bd->w;
9207    if (h) *h = bd->h;
9208    if (move) *move = EINA_TRUE;
9209
9210    if (bd->client.e.state.rot.geom_hint)
9211      {
9212         switch (ang)
9213           {
9214            case   0:
9215               _w = bd->client.e.state.rot.geom[0].w;
9216               _h = bd->client.e.state.rot.geom[0].h;
9217               if (_w == 0) _w = bd->w;
9218               if (_h == 0) _h = bd->h;
9219               _x = 0; _y = zone->h - _h;
9220               break;
9221            case  90:
9222               _w = bd->client.e.state.rot.geom[1].w;
9223               _h = bd->client.e.state.rot.geom[1].h;
9224               if (_w == 0) _w = bd->w;
9225               if (_h == 0) _h = bd->h;
9226               _x = zone->w - _w; _y = 0;
9227               break;
9228            case 180:
9229               _w = bd->client.e.state.rot.geom[2].w;
9230               _h = bd->client.e.state.rot.geom[2].h;
9231               if (_w == 0) _w = bd->w;
9232               if (_h == 0) _h = bd->h;
9233               _x = 0; _y = 0;
9234               break;
9235            case 270:
9236               _w = bd->client.e.state.rot.geom[3].w;
9237               _h = bd->client.e.state.rot.geom[3].h;
9238               if (_w == 0) _w = bd->w;
9239               if (_h == 0) _h = bd->h;
9240               _x = 0; _y = 0;
9241               break;
9242           }
9243
9244         if (x) *x = _x;
9245         if (y) *y = _y;
9246         if (w) *w = _w;
9247         if (h) *h = _h;
9248
9249         if (!((rot.vkbd) && (rot.vkbd == bd)))
9250           {
9251              if (x) *x = bd->x;
9252              if (y) *y = bd->y;
9253              if (move) *move = EINA_FALSE;
9254           }
9255
9256         res = EINA_TRUE;
9257      }
9258
9259    if (res)
9260      {
9261         _x = 0; _y = 0; _w = 0; _h = 0;
9262         if (x) _x = *x;
9263         if (y) _y = *y;
9264         if (w) _w = *w;
9265         if (h) _h = *h;
9266         if (move) _move = *move;
9267
9268         ELBF(ELBT_ROT, 1, bd->client.win,
9269              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
9270              ang, _x, _y, _w, _h, _move);
9271      }
9272
9273    return res;
9274 }
9275 #endif
9276
9277 static Eina_Bool
9278 _e_border_post_move_resize_job(void *data)
9279 {
9280    E_Border *bd;
9281
9282    bd = (E_Border *)data;
9283    if (bd->post_move)
9284      {
9285         E_Border *tmp;
9286         Eina_List *l;
9287
9288         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
9289           ecore_x_window_move(tmp->win,
9290                               bd->x +
9291                               bd->client_inset.l +
9292                               bd->fx.x +
9293                               tmp->client.e.state.video_position.x,
9294                               bd->y +
9295                               bd->client_inset.t +
9296                               bd->fx.y +
9297                               tmp->client.e.state.video_position.y);
9298      }
9299    if (bd->client.e.state.video)
9300      {
9301         E_Border *parent;
9302
9303         parent = bd->client.e.state.video_parent_border;
9304         ecore_x_window_move(bd->win,
9305                             parent->x +
9306                             parent->client_inset.l +
9307                             parent->fx.x +
9308                             bd->client.e.state.video_position.x,
9309                             parent->y +
9310                             parent->client_inset.t +
9311                             parent->fx.y +
9312                             bd->client.e.state.video_position.y);
9313      }
9314    else if ((bd->post_move) && (bd->post_resize))
9315      {
9316         ecore_x_window_move_resize(bd->win,
9317                                    bd->x + bd->fx.x,
9318                                    bd->y + bd->fx.y,
9319                                    bd->w, bd->h);
9320      }
9321    else if (bd->post_move)
9322      {
9323         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
9324      }
9325    else if (bd->post_resize)
9326      {
9327         ecore_x_window_resize(bd->win, bd->w, bd->h);
9328      }
9329
9330    if (bd->client.e.state.video)
9331      {
9332         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
9333                 bd->win,
9334                 bd->client.e.state.video_parent_border->x +
9335                 bd->client.e.state.video_parent_border->client_inset.l +
9336                 bd->client.e.state.video_parent_border->fx.x +
9337                 bd->client.e.state.video_position.x,
9338                 bd->client.e.state.video_parent_border->y +
9339                 bd->client.e.state.video_parent_border->client_inset.t +
9340                 bd->client.e.state.video_parent_border->fx.y +
9341                 bd->client.e.state.video_position.y,
9342                 bd->w, bd->h);
9343      }
9344
9345    if (bd->post_show)
9346      {
9347         if (bd->visible)
9348           {
9349              bd->post_job = NULL;
9350              _e_border_show(bd);
9351           }
9352      }
9353    bd->post_show = 0;
9354    bd->post_move = 0;
9355    bd->post_resize = 0;
9356    bd->post_job = NULL;
9357    return ECORE_CALLBACK_CANCEL;
9358 }
9359
9360 static void
9361 _e_border_container_layout_hook(E_Container *con)
9362 {
9363    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
9364 }
9365
9366 static void
9367 _e_border_eval0(E_Border *bd)
9368 {
9369    int change_urgent = 0;
9370    int rem_change = 0;
9371 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9372    Eina_Bool need_desk_set = EINA_FALSE;
9373 #endif
9374 #ifdef _F_ZONE_WINDOW_ROTATION_
9375    Eina_Bool need_rotation_set = EINA_FALSE;
9376
9377    if ((e_config->wm_win_rotation) &&
9378        (bd->client.icccm.fetch.transient_for))
9379      {
9380         if (((rot.vkbd) && (rot.vkbd == bd)) ||
9381             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
9382           {
9383              need_rotation_set = EINA_TRUE;
9384              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
9385           }
9386      }
9387 #endif
9388
9389    if (e_object_is_del(E_OBJECT(bd)))
9390      {
9391         CRI("_e_border_eval(%p) with deleted border!\n", bd);
9392         bd->changed = 0;
9393         return;
9394      }
9395
9396    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
9397
9398    bd->changes.border = 0;
9399
9400    /* fetch any info queued to be fetched */
9401    if (bd->client.netwm.fetch.state)
9402      {
9403         e_hints_window_state_get(bd);
9404         bd->client.netwm.fetch.state = 0;
9405         rem_change = 1;
9406      }
9407    if (bd->client.icccm.fetch.client_leader)
9408      {
9409         /* TODO: What do to if the client leader isn't mapped yet? */
9410         E_Border *bd_leader = NULL;
9411
9412         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
9413         if (bd->client.icccm.client_leader)
9414           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
9415         if (bd->leader)
9416           {
9417              if (bd->leader != bd_leader)
9418                {
9419                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
9420                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
9421                   bd->leader = NULL;
9422                }
9423              else
9424                bd_leader = NULL;
9425           }
9426         /* If this border is the leader of the group, don't register itself */
9427         if ((bd_leader) && (bd_leader != bd))
9428           {
9429              bd_leader->group = eina_list_append(bd_leader->group, bd);
9430              bd->leader = bd_leader;
9431              /* Only set the window modal to the leader it there is no parent */
9432              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
9433                  ((!bd->parent) || (bd->parent->modal != bd)))
9434                {
9435                   bd->leader->modal = bd;
9436                   if (bd->leader->focused)
9437                     e_border_focus_set(bd, 1, 1);
9438                   else
9439                     {
9440                        Eina_List *l;
9441                        E_Border *child;
9442
9443                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9444                          {
9445                             if ((child != bd) && (child->focused))
9446                               e_border_focus_set(bd, 1, 1);
9447                          }
9448                     }
9449                }
9450           }
9451         bd->client.icccm.fetch.client_leader = 0;
9452         rem_change = 1;
9453      }
9454    if (bd->client.icccm.fetch.title)
9455      {
9456         char *title = ecore_x_icccm_title_get(bd->client.win);
9457         eina_stringshare_replace(&bd->client.icccm.title, title);
9458         if (title) free(title);
9459
9460         if (bd->bg_object)
9461           edje_object_part_text_set(bd->bg_object, "e.text.title",
9462                                     bd->client.icccm.title);
9463         bd->client.icccm.fetch.title = 0;
9464         rem_change = 1;
9465      }
9466    if (bd->client.netwm.fetch.name)
9467      {
9468         char *name;
9469         ecore_x_netwm_name_get(bd->client.win, &name);
9470         eina_stringshare_replace(&bd->client.netwm.name, name);
9471         if (name) free(name);
9472
9473         if (bd->bg_object)
9474           edje_object_part_text_set(bd->bg_object, "e.text.title",
9475                                     bd->client.netwm.name);
9476         bd->client.netwm.fetch.name = 0;
9477         rem_change = 1;
9478      }
9479    if (bd->client.icccm.fetch.name_class)
9480      {
9481         const char *pname, *pclass;
9482         char *nname, *nclass;
9483
9484         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
9485         pname = bd->client.icccm.name;
9486         pclass = bd->client.icccm.class;
9487         bd->client.icccm.name = eina_stringshare_add(nname);
9488         bd->client.icccm.class = eina_stringshare_add(nclass);
9489         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
9490           e_bindings_mapping_change_enable(EINA_FALSE);
9491 #ifdef _F_ZONE_WINDOW_ROTATION_
9492         if (e_config->wm_win_rotation)
9493           {
9494              if ((bd->client.icccm.name) && (bd->client.icccm.class))
9495                {
9496                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
9497                       (!strcmp(bd->client.icccm.class, "ISF")))
9498                     {
9499                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
9500                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
9501                        rot.vkbd = bd;
9502                     }
9503                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
9504                            (!strcmp(bd->client.icccm.class, "ISF")))
9505                     {
9506                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
9507                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
9508                        rot.vkbd_prediction = bd;
9509                     }
9510                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
9511                            (!strcmp(bd->client.icccm.class, "ISF")))
9512                     {
9513                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
9514                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
9515                     }
9516                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
9517                            (!strcmp(bd->client.icccm.class, "ISF")))
9518                     {
9519                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
9520                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
9521                     }
9522                }
9523           }
9524 #endif
9525         if (nname) free(nname);
9526         if (nclass) free(nclass);
9527
9528         if (!((bd->client.icccm.name == pname) &&
9529               (bd->client.icccm.class == pclass)))
9530           bd->changes.icon = 1;
9531
9532         if (pname) eina_stringshare_del(pname);
9533         if (pclass) eina_stringshare_del(pclass);
9534         bd->client.icccm.fetch.name_class = 0;
9535         bd->changes.icon = 1;
9536         rem_change = 1;
9537      }
9538    if (bd->client.icccm.fetch.state)
9539      {
9540         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
9541         bd->client.icccm.fetch.state = 0;
9542         rem_change = 1;
9543      }
9544    if (bd->client.e.fetch.state)
9545      {
9546         e_hints_window_e_state_get(bd);
9547         bd->client.e.fetch.state = 0;
9548         rem_change = 1;
9549      }
9550 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9551    if (bd->client.e.fetch.profile_list)
9552      {
9553         const char **profiles = NULL;
9554         const char *str;
9555         int num = 0, i;
9556
9557         if (bd->client.e.state.profile)
9558           eina_stringshare_del(bd->client.e.state.profile);
9559         EINA_LIST_FREE(bd->client.e.state.profiles, str)
9560           {
9561              if (str) eina_stringshare_del(str);
9562           }
9563         bd->client.e.state.profile = NULL;
9564         bd->client.e.state.profiles = NULL;
9565         bd->client.e.state.profile_list = 0;
9566
9567         if (ecore_x_e_window_profile_list_get(bd->client.win,
9568                                               &profiles, &num))
9569           {
9570              bd->client.e.state.profile_list = 1;
9571              for (i = 0; i < num; i++)
9572                {
9573                   str = eina_stringshare_add(profiles[i]);
9574                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
9575                }
9576
9577              /* We should set desk to contain given border after creating E_BORDER_ADD event.
9578               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
9579               */
9580              need_desk_set = EINA_TRUE;
9581           }
9582         else
9583           {
9584              if (strcmp(bd->desk->window_profile,
9585                         e_config->desktop_default_window_profile) != 0)
9586                {
9587                   ecore_x_e_window_profile_set(bd->client.win,
9588                                                bd->desk->window_profile);
9589                }
9590           }
9591
9592         if (profiles)
9593           {
9594              for (i = 0; i < num; i++)
9595                 if (profiles[i]) free(profiles[i]);
9596              free(profiles);
9597           }
9598
9599         bd->client.e.fetch.profile_list = 0;
9600      }
9601 #endif
9602 #ifdef _F_ZONE_WINDOW_ROTATION_
9603    if ((e_config->wm_win_rotation) &&
9604        (bd->client.e.fetch.rot.support))
9605      {
9606         int ret = 0;
9607         unsigned int support = 0;
9608
9609         ret = ecore_x_window_prop_card32_get
9610           (bd->client.win,
9611           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
9612           &support, 1);
9613
9614         bd->client.e.state.rot.support = 0;
9615         if ((ret == 1) && (support == 1))
9616           bd->client.e.state.rot.support = 1;
9617
9618         if (bd->client.e.state.rot.support)
9619           need_rotation_set = EINA_TRUE;
9620
9621         bd->client.e.fetch.rot.support = 0;
9622      }
9623    if ((e_config->wm_win_rotation) &&
9624        (bd->client.e.fetch.rot.geom_hint))
9625      {
9626         Eina_Rectangle r[4];
9627         int i, x, y, w, h;
9628         bd->client.e.state.rot.geom_hint = 0;
9629         for (i = 0; i < 4; i++)
9630           {
9631              r[i].x = bd->client.e.state.rot.geom[i].x;
9632              r[i].y = bd->client.e.state.rot.geom[i].y;
9633              r[i].w = bd->client.e.state.rot.geom[i].w;
9634              r[i].h = bd->client.e.state.rot.geom[i].h;
9635
9636              bd->client.e.state.rot.geom[i].x = 0;
9637              bd->client.e.state.rot.geom[i].y = 0;
9638              bd->client.e.state.rot.geom[i].w = 0;
9639              bd->client.e.state.rot.geom[i].h = 0;
9640           }
9641
9642         for (i = 0; i < 4; i++)
9643           {
9644              x = 0; y = 0; w = 0; h = 0;
9645              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
9646                {
9647                   bd->client.e.state.rot.geom_hint = 1;
9648                   bd->client.e.state.rot.geom[i].x = x;
9649                   bd->client.e.state.rot.geom[i].y = y;
9650                   bd->client.e.state.rot.geom[i].w = w;
9651                   bd->client.e.state.rot.geom[i].h = h;
9652
9653                   if (!((r[i].x == x) && (r[i].y == y) &&
9654                         (r[i].w == w) && (r[i].h == h)))
9655                     {
9656                        need_rotation_set = EINA_TRUE;
9657                     }
9658                }
9659           }
9660         bd->client.e.fetch.rot.geom_hint = 0;
9661      }
9662    if ((e_config->wm_win_rotation) &&
9663        (bd->client.e.fetch.rot.app_set))
9664      {
9665         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
9666         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
9667         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
9668
9669         if (_prev_app_set != bd->client.e.state.rot.app_set)
9670           need_rotation_set = EINA_TRUE;
9671
9672         bd->client.e.fetch.rot.app_set = 0;
9673      }
9674    if ((e_config->wm_win_rotation) &&
9675        (bd->client.e.fetch.rot.preferred_rot))
9676      {
9677         int r = 0, _prev_preferred_rot;
9678         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
9679         bd->client.e.state.rot.preferred_rot = -1;
9680         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
9681           {
9682              bd->client.e.state.rot.preferred_rot = r;
9683              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
9684           }
9685         else
9686           {
9687              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
9688           }
9689
9690         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
9691           need_rotation_set = EINA_TRUE;
9692
9693         bd->client.e.fetch.rot.preferred_rot = 0;
9694      }
9695    if ((e_config->wm_win_rotation) &&
9696        (bd->client.e.fetch.rot.available_rots))
9697      {
9698         Eina_Bool res, diff = EINA_FALSE;
9699         int *rots = NULL;
9700         unsigned int count = 0, i = 0;
9701         int _prev_rots[4] = { -1, };
9702
9703         if (bd->client.e.state.rot.available_rots)
9704           {
9705              memcpy(_prev_rots,
9706                     bd->client.e.state.rot.available_rots,
9707                     (sizeof(int) * bd->client.e.state.rot.count));
9708
9709              E_FREE(bd->client.e.state.rot.available_rots);
9710           }
9711
9712         bd->client.e.state.rot.count = 0;
9713
9714         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
9715                                                                 &rots, &count);
9716         if ((res) && (count > 0) && (rots))
9717           {
9718              bd->client.e.state.rot.available_rots = rots;
9719              bd->client.e.state.rot.count = count;
9720
9721              for (i = 0; i < count; i++)
9722                {
9723                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
9724                   if ((!diff) && (_prev_rots[i] != rots[i]))
9725                     {
9726                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
9727                             count, i, _prev_rots[i], rots[i]);
9728                        diff = EINA_TRUE;
9729                     }
9730                }
9731           }
9732         else
9733           {
9734              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9735              diff = EINA_TRUE;
9736           }
9737
9738         if (diff) need_rotation_set = EINA_TRUE;
9739         bd->client.e.fetch.rot.available_rots = 0;
9740      }
9741 #endif
9742    if (bd->client.netwm.fetch.type)
9743      {
9744         e_hints_window_type_get(bd);
9745         if ((!bd->lock_border) || (!bd->client.border.name))
9746           bd->client.border.changed = 1;
9747
9748         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9749           {
9750              if (!bd->client.netwm.state.skip_pager)
9751                {
9752                   bd->client.netwm.state.skip_pager = 1;
9753                   bd->client.netwm.update.state = 1;
9754                }
9755              if (!bd->client.netwm.state.skip_taskbar)
9756                {
9757                   bd->client.netwm.state.skip_taskbar = 1;
9758                   bd->client.netwm.update.state = 1;
9759                }
9760           }
9761         bd->client.netwm.fetch.type = 0;
9762      }
9763    if (bd->client.icccm.fetch.machine)
9764      {
9765         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9766
9767         if ((!machine) && (bd->client.icccm.client_leader))
9768           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9769
9770         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9771         if (machine) free(machine);
9772
9773         bd->client.icccm.fetch.machine = 0;
9774         rem_change = 1;
9775      }
9776    if (bd->client.icccm.fetch.command)
9777      {
9778         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9779           {
9780              int i;
9781
9782              for (i = 0; i < bd->client.icccm.command.argc; i++)
9783                free(bd->client.icccm.command.argv[i]);
9784              free(bd->client.icccm.command.argv);
9785           }
9786         bd->client.icccm.command.argc = 0;
9787         bd->client.icccm.command.argv = NULL;
9788         ecore_x_icccm_command_get(bd->client.win,
9789                                   &(bd->client.icccm.command.argc),
9790                                   &(bd->client.icccm.command.argv));
9791         if ((bd->client.icccm.client_leader) &&
9792             (!bd->client.icccm.command.argv))
9793           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9794                                     &(bd->client.icccm.command.argc),
9795                                     &(bd->client.icccm.command.argv));
9796         bd->client.icccm.fetch.command = 0;
9797         rem_change = 1;
9798      }
9799    if (bd->client.icccm.fetch.hints)
9800      {
9801         Eina_Bool accepts_focus, is_urgent;
9802
9803         accepts_focus = EINA_TRUE;
9804         is_urgent = EINA_FALSE;
9805         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9806         if (ecore_x_icccm_hints_get(bd->client.win,
9807                                     &accepts_focus,
9808                                     &bd->client.icccm.initial_state,
9809                                     &bd->client.icccm.icon_pixmap,
9810                                     &bd->client.icccm.icon_mask,
9811                                     &bd->client.icccm.icon_window,
9812                                     &bd->client.icccm.window_group,
9813                                     &is_urgent))
9814           {
9815              bd->client.icccm.accepts_focus = accepts_focus;
9816              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9817                change_urgent = 1;
9818              bd->client.icccm.urgent = is_urgent;
9819
9820              /* If this is a new window, set the state as requested. */
9821              if ((bd->new_client) &&
9822                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9823                {
9824                   e_border_iconify(bd);
9825                   e_border_hide(bd, 1);
9826                }
9827           }
9828         bd->client.icccm.fetch.hints = 0;
9829         rem_change = 1;
9830      }
9831    if (bd->client.icccm.fetch.size_pos_hints)
9832      {
9833         Eina_Bool request_pos;
9834
9835         request_pos = EINA_FALSE;
9836         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9837                                              &request_pos,
9838                                              &bd->client.icccm.gravity,
9839                                              &bd->client.icccm.min_w,
9840                                              &bd->client.icccm.min_h,
9841                                              &bd->client.icccm.max_w,
9842                                              &bd->client.icccm.max_h,
9843                                              &bd->client.icccm.base_w,
9844                                              &bd->client.icccm.base_h,
9845                                              &bd->client.icccm.step_w,
9846                                              &bd->client.icccm.step_h,
9847                                              &bd->client.icccm.min_aspect,
9848                                              &bd->client.icccm.max_aspect))
9849           {
9850              bd->client.icccm.request_pos = request_pos;
9851           }
9852         else
9853           {
9854           }
9855         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9856         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9857         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9858         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9859         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9860         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9861         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9862         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9863         // if doing a resize, fix it up
9864         if (bd->resize_mode != RESIZE_NONE)
9865           {
9866              int x, y, w, h, new_w, new_h;
9867
9868              x = bd->x;
9869              y = bd->y;
9870              w = bd->w;
9871              h = bd->h;
9872              new_w = w;
9873              new_h = h;
9874              e_border_resize_limit(bd, &new_w, &new_h);
9875              if ((bd->resize_mode == RESIZE_TL) ||
9876                  (bd->resize_mode == RESIZE_L) ||
9877                  (bd->resize_mode == RESIZE_BL))
9878                x += (w - new_w);
9879              if ((bd->resize_mode == RESIZE_TL) ||
9880                  (bd->resize_mode == RESIZE_T) ||
9881                  (bd->resize_mode == RESIZE_TR))
9882                y += (h - new_h);
9883              e_border_move_resize(bd, x, y, new_w, new_h);
9884           }
9885         bd->client.icccm.fetch.size_pos_hints = 0;
9886         rem_change = 1;
9887      }
9888    if (bd->client.icccm.fetch.protocol)
9889      {
9890         int i, num;
9891         Ecore_X_WM_Protocol *proto;
9892
9893         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9894         if (proto)
9895           {
9896              for (i = 0; i < num; i++)
9897                {
9898                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9899                     bd->client.icccm.delete_request = 1;
9900                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9901                     bd->client.icccm.take_focus = 1;
9902                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9903                     bd->client.netwm.ping = 1;
9904                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9905                     {
9906                        bd->client.netwm.sync.request = 1;
9907                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9908                                                            &bd->client.netwm.sync.counter))
9909                          bd->client.netwm.sync.request = 0;
9910                     }
9911                }
9912              free(proto);
9913           }
9914         if (bd->client.netwm.ping)
9915           e_border_ping(bd);
9916         else
9917           {
9918              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9919              bd->ping_poller = NULL;
9920           }
9921         bd->client.icccm.fetch.protocol = 0;
9922      }
9923    if (bd->client.icccm.fetch.transient_for)
9924      {
9925         /* TODO: What do to if the transient for isn't mapped yet? */
9926         E_Border *bd_parent = NULL;
9927 #ifdef _F_DEICONIFY_APPROVE_
9928         Eina_Bool change_parent = EINA_FALSE;
9929 #endif
9930
9931         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9932         if (bd->client.icccm.transient_for)
9933           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9934         /* If we already have a parent, remove it */
9935         if (bd->parent)
9936           {
9937              if (bd_parent != bd->parent)
9938                {
9939                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9940                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9941                   bd->parent = NULL;
9942                }
9943              else
9944                bd_parent = NULL;
9945           }
9946         if ((bd_parent) && (bd_parent != bd) &&
9947             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9948           {
9949              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9950              bd->parent = bd_parent;
9951 #ifdef _F_DEICONIFY_APPROVE_
9952              change_parent = EINA_TRUE;
9953 #endif
9954           }
9955         if (bd->parent)
9956           {
9957              e_border_layer_set(bd, bd->parent->layer);
9958              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9959                {
9960                   Ecore_X_Window_Attributes attr;
9961                   bd->parent->modal = bd;
9962                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9963                   bd->parent->saved.event_mask = attr.event_mask.mine;
9964                   bd->parent->lock_close = 1;
9965                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9966                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9967                }
9968
9969              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9970                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9971                bd->take_focus = 1;
9972           }
9973
9974 #ifdef _F_DEICONIFY_APPROVE_
9975         if (change_parent)
9976           {
9977              bd->client.e.state.deiconify_approve.render_done = 0;
9978
9979              E_Border *ancestor_bd;
9980              ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
9981              if ((ancestor_bd) &&
9982                  (!e_object_is_del(E_OBJECT(ancestor_bd))))
9983                {
9984                   ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
9985                   bd->client.e.state.deiconify_approve.ancestor = NULL;
9986
9987                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
9988                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
9989                     {
9990                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
9991                          {
9992                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
9993                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
9994                             e_border_uniconify(ancestor_bd);
9995                          }
9996                     }
9997                }
9998           }
9999 #endif
10000         bd->client.icccm.fetch.transient_for = 0;
10001         rem_change = 1;
10002      }
10003    if (bd->client.icccm.fetch.window_role)
10004      {
10005         char *role = ecore_x_icccm_window_role_get(bd->client.win);
10006         eina_stringshare_replace(&bd->client.icccm.window_role, role);
10007         if (role) free(role);
10008
10009         bd->client.icccm.fetch.window_role = 0;
10010         rem_change = 1;
10011      }
10012    if (bd->client.icccm.fetch.icon_name)
10013      {
10014         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
10015         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
10016         if (icon_name) free(icon_name);
10017
10018         bd->client.icccm.fetch.icon_name = 0;
10019         rem_change = 1;
10020      }
10021    if (bd->client.netwm.fetch.icon_name)
10022      {
10023         char *icon_name;
10024         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
10025         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
10026         if (icon_name) free(icon_name);
10027
10028         bd->client.netwm.fetch.icon_name = 0;
10029         rem_change = 1;
10030      }
10031    if (bd->client.netwm.fetch.icon)
10032      {
10033         int i;
10034         if (bd->client.netwm.icons)
10035           {
10036              for (i = 0; i < bd->client.netwm.num_icons; i++)
10037                {
10038                   free(bd->client.netwm.icons[i].data);
10039                   bd->client.netwm.icons[i].data = NULL;
10040                }
10041              free(bd->client.netwm.icons);
10042           }
10043         bd->client.netwm.icons = NULL;
10044         bd->client.netwm.num_icons = 0;
10045         if (ecore_x_netwm_icons_get(bd->client.win,
10046                                      &bd->client.netwm.icons,
10047                                      &bd->client.netwm.num_icons))
10048           {
10049              // unless the rest of e17 uses border icons OTHER than icon #0
10050              // then free the rest that we don't need anymore.
10051              for (i = 1; i < bd->client.netwm.num_icons; i++)
10052                {
10053                   free(bd->client.netwm.icons[i].data);
10054                   bd->client.netwm.icons[i].data = NULL;
10055                }
10056              bd->client.netwm.num_icons = 1;
10057              bd->changes.icon = 1;
10058           }
10059         bd->client.netwm.fetch.icon = 0;
10060      }
10061    if (bd->client.netwm.fetch.user_time)
10062      {
10063         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
10064         bd->client.netwm.fetch.user_time = 0;
10065      }
10066    if (bd->client.netwm.fetch.strut)
10067      {
10068         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
10069                                              &bd->client.netwm.strut.left,
10070                                              &bd->client.netwm.strut.right,
10071                                              &bd->client.netwm.strut.top,
10072                                              &bd->client.netwm.strut.bottom,
10073                                              &bd->client.netwm.strut.left_start_y,
10074                                              &bd->client.netwm.strut.left_end_y,
10075                                              &bd->client.netwm.strut.right_start_y,
10076                                              &bd->client.netwm.strut.right_end_y,
10077                                              &bd->client.netwm.strut.top_start_x,
10078                                              &bd->client.netwm.strut.top_end_x,
10079                                              &bd->client.netwm.strut.bottom_start_x,
10080                                              &bd->client.netwm.strut.bottom_end_x))
10081           {
10082              ecore_x_netwm_strut_get(bd->client.win,
10083                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
10084                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
10085
10086              bd->client.netwm.strut.left_start_y = 0;
10087              bd->client.netwm.strut.left_end_y = 0;
10088              bd->client.netwm.strut.right_start_y = 0;
10089              bd->client.netwm.strut.right_end_y = 0;
10090              bd->client.netwm.strut.top_start_x = 0;
10091              bd->client.netwm.strut.top_end_x = 0;
10092              bd->client.netwm.strut.bottom_start_x = 0;
10093              bd->client.netwm.strut.bottom_end_x = 0;
10094           }
10095         bd->client.netwm.fetch.strut = 0;
10096      }
10097    if (bd->client.qtopia.fetch.soft_menu)
10098      {
10099         e_hints_window_qtopia_soft_menu_get(bd);
10100         bd->client.qtopia.fetch.soft_menu = 0;
10101         rem_change = 1;
10102      }
10103    if (bd->client.qtopia.fetch.soft_menus)
10104      {
10105         e_hints_window_qtopia_soft_menus_get(bd);
10106         bd->client.qtopia.fetch.soft_menus = 0;
10107         rem_change = 1;
10108      }
10109    if (bd->client.vkbd.fetch.state)
10110      {
10111         e_hints_window_virtual_keyboard_state_get(bd);
10112         bd->client.vkbd.fetch.state = 0;
10113         rem_change = 1;
10114      }
10115    if (bd->client.vkbd.fetch.vkbd)
10116      {
10117         e_hints_window_virtual_keyboard_get(bd);
10118         bd->client.vkbd.fetch.vkbd = 0;
10119         rem_change = 1;
10120      }
10121    if (bd->client.illume.conformant.fetch.conformant)
10122      {
10123         bd->client.illume.conformant.conformant =
10124           ecore_x_e_illume_conformant_get(bd->client.win);
10125         bd->client.illume.conformant.fetch.conformant = 0;
10126      }
10127    if (bd->client.illume.quickpanel.fetch.state)
10128      {
10129         bd->client.illume.quickpanel.state =
10130           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
10131         bd->client.illume.quickpanel.fetch.state = 0;
10132      }
10133    if (bd->client.illume.quickpanel.fetch.quickpanel)
10134      {
10135         bd->client.illume.quickpanel.quickpanel =
10136           ecore_x_e_illume_quickpanel_get(bd->client.win);
10137         bd->client.illume.quickpanel.fetch.quickpanel = 0;
10138      }
10139    if (bd->client.illume.quickpanel.fetch.priority.major)
10140      {
10141         bd->client.illume.quickpanel.priority.major =
10142           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
10143         bd->client.illume.quickpanel.fetch.priority.major = 0;
10144      }
10145    if (bd->client.illume.quickpanel.fetch.priority.minor)
10146      {
10147         bd->client.illume.quickpanel.priority.minor =
10148           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
10149         bd->client.illume.quickpanel.fetch.priority.minor = 0;
10150      }
10151    if (bd->client.illume.quickpanel.fetch.zone)
10152      {
10153         bd->client.illume.quickpanel.zone =
10154           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
10155         bd->client.illume.quickpanel.fetch.zone = 0;
10156      }
10157    if (bd->client.illume.drag.fetch.drag)
10158      {
10159         bd->client.illume.drag.drag =
10160           ecore_x_e_illume_drag_get(bd->client.win);
10161         bd->client.illume.drag.fetch.drag = 0;
10162      }
10163    if (bd->client.illume.drag.fetch.locked)
10164      {
10165         bd->client.illume.drag.locked =
10166           ecore_x_e_illume_drag_locked_get(bd->client.win);
10167         bd->client.illume.drag.fetch.locked = 0;
10168      }
10169    if (bd->client.illume.win_state.fetch.state)
10170      {
10171         bd->client.illume.win_state.state =
10172            ecore_x_e_illume_window_state_get(bd->client.win);
10173         bd->client.illume.win_state.fetch.state = 0;
10174      }
10175    if (bd->changes.shape)
10176      {
10177         Ecore_X_Rectangle *rects;
10178         int num;
10179
10180         bd->changes.shape = 0;
10181         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
10182         if (rects)
10183           {
10184              int cw = 0, ch = 0;
10185
10186              /* This doesn't fix the race, but makes it smaller. we detect
10187               * this and if cw and ch != client w/h then mark this as needing
10188               * a shape change again to fixup next event loop.
10189               */
10190              ecore_x_window_size_get(bd->client.win, &cw, &ch);
10191              if ((cw != bd->client.w) || (ch != bd->client.h))
10192                bd->changes.shape = 1;
10193              if ((num == 1) &&
10194                  (rects[0].x == 0) &&
10195                  (rects[0].y == 0) &&
10196                  ((int)rects[0].width == cw) &&
10197                  ((int)rects[0].height == ch))
10198                {
10199                   if (bd->client.shaped)
10200                     {
10201                        bd->client.shaped = 0;
10202                        if (!bd->bordername)
10203                          bd->client.border.changed = 1;
10204                     }
10205                }
10206              else
10207                {
10208                   if (!bd->client.shaped)
10209                     {
10210                        bd->client.shaped = 1;
10211                        if (!bd->bordername)
10212                          bd->client.border.changed = 1;
10213                     }
10214                }
10215              free(rects);
10216           }
10217         else
10218           {
10219              // FIXME: no rects i think can mean... totally empty window
10220              bd->client.shaped = 0;
10221              if (!bd->bordername)
10222                bd->client.border.changed = 1;
10223           }
10224         bd->need_shape_merge = 1;
10225      }
10226    if (bd->changes.shape_input)
10227      {
10228         Ecore_X_Rectangle *rects;
10229         int num;
10230
10231         bd->changes.shape_input = 0;
10232         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
10233         if (rects)
10234           {
10235              int cw = 0, ch = 0;
10236
10237              /* This doesn't fix the race, but makes it smaller. we detect
10238               * this and if cw and ch != client w/h then mark this as needing
10239               * a shape change again to fixup next event loop.
10240               */
10241              ecore_x_window_size_get(bd->client.win, &cw, &ch);
10242              if ((cw != bd->client.w) || (ch != bd->client.h))
10243                bd->changes.shape_input = 1;
10244              if ((num == 1) &&
10245                  (rects[0].x == 0) &&
10246                  (rects[0].y == 0) &&
10247                  ((int)rects[0].width == cw) &&
10248                  ((int)rects[0].height == ch))
10249                {
10250                   if (bd->shaped_input)
10251                     {
10252                        bd->shaped_input = 0;
10253                        if (!bd->bordername)
10254                          bd->client.border.changed = 1;
10255                     }
10256                }
10257              else
10258                {
10259                   if (!bd->shaped_input)
10260                     {
10261                        bd->shaped_input = 1;
10262                        if (!bd->bordername)
10263                          bd->client.border.changed = 1;
10264                     }
10265                }
10266              free(rects);
10267           }
10268         else
10269           {
10270              bd->shaped_input = 1;
10271              if (!bd->bordername)
10272                bd->client.border.changed = 1;
10273           }
10274         bd->need_shape_merge = 1;
10275      }
10276    if (bd->client.mwm.fetch.hints)
10277      {
10278         int pb;
10279
10280         bd->client.mwm.exists =
10281           ecore_x_mwm_hints_get(bd->client.win,
10282                                 &bd->client.mwm.func,
10283                                 &bd->client.mwm.decor,
10284                                 &bd->client.mwm.input);
10285         pb = bd->client.mwm.borderless;
10286         bd->client.mwm.borderless = 0;
10287         if (bd->client.mwm.exists)
10288           {
10289              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
10290                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
10291                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
10292                bd->client.mwm.borderless = 1;
10293           }
10294         if (bd->client.mwm.borderless != pb)
10295           {
10296              if ((!bd->lock_border) || (!bd->client.border.name))
10297                bd->client.border.changed = 1;
10298           }
10299         bd->client.mwm.fetch.hints = 0;
10300         rem_change = 1;
10301      }
10302    if (bd->client.e.fetch.video_parent)
10303      {
10304         /* unlinking child/parent */
10305         if (bd->client.e.state.video_parent_border != NULL)
10306           {
10307              bd->client.e.state.video_parent_border->client.e.state.video_child =
10308                eina_list_remove
10309                (bd->client.e.state.video_parent_border->client.e.state.video_child,
10310                    bd);
10311           }
10312
10313         ecore_x_window_prop_card32_get(bd->client.win,
10314                                        ECORE_X_ATOM_E_VIDEO_PARENT,
10315                                        &bd->client.e.state.video_parent,
10316                                        1);
10317
10318         /* linking child/parent */
10319         if (bd->client.e.state.video_parent != 0)
10320           {
10321              E_Border *tmp;
10322              Eina_List *l;
10323
10324              EINA_LIST_FOREACH(borders, l, tmp)
10325                if (tmp->client.win == bd->client.e.state.video_parent)
10326                  {
10327                     /* fprintf(stderr, "child added to parent \\o/\n"); */
10328                     bd->client.e.state.video_parent_border = tmp;
10329                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
10330                                                                        bd);
10331                     if (bd->desk != tmp->desk)
10332                       e_border_desk_set(bd, tmp->desk);
10333                     break;
10334                  }
10335           }
10336
10337         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
10338
10339         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
10340         rem_change = 1;
10341      }
10342    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
10343      {
10344         unsigned int xy[2];
10345
10346         ecore_x_window_prop_card32_get(bd->client.win,
10347                                        ECORE_X_ATOM_E_VIDEO_POSITION,
10348                                        xy,
10349                                        2);
10350         bd->client.e.state.video_position.x = xy[0];
10351         bd->client.e.state.video_position.y = xy[1];
10352         bd->client.e.state.video_position.updated = 1;
10353         bd->client.e.fetch.video_position = 0;
10354         bd->x = bd->client.e.state.video_position.x;
10355         bd->y = bd->client.e.state.video_position.y;
10356
10357         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
10358      }
10359    if (bd->client.netwm.update.state)
10360      {
10361         e_hints_window_state_set(bd);
10362         /* Some stats might change the border, like modal */
10363         if (((!bd->lock_border) || (!bd->client.border.name)) &&
10364             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10365           {
10366              bd->client.border.changed = 1;
10367           }
10368         if (bd->parent)
10369           {
10370              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10371                {
10372                   bd->parent->modal = bd;
10373                   if (bd->parent->focused)
10374                     e_border_focus_set(bd, 1, 1);
10375                }
10376           }
10377         else if (bd->leader)
10378           {
10379              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10380                {
10381                   bd->leader->modal = bd;
10382                   if (bd->leader->focused)
10383                     e_border_focus_set(bd, 1, 1);
10384                   else
10385                     {
10386                        Eina_List *l;
10387                        E_Border *child;
10388
10389                        EINA_LIST_FOREACH(bd->leader->group, l, child)
10390                          {
10391                             if ((child != bd) && (child->focused))
10392                               e_border_focus_set(bd, 1, 1);
10393                          }
10394                     }
10395                }
10396           }
10397         bd->client.netwm.update.state = 0;
10398      }
10399
10400    if (bd->new_client)
10401      {
10402         E_Event_Border_Add *ev;
10403         E_Exec_Instance *inst;
10404
10405         ev = E_NEW(E_Event_Border_Add, 1);
10406         ev->border = bd;
10407         e_object_ref(E_OBJECT(bd));
10408         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
10409         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
10410
10411         if ((!bd->lock_border) || (!bd->client.border.name))
10412           bd->client.border.changed = 1;
10413
10414           {
10415              char *str = NULL;
10416
10417              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
10418                  ((bd->client.icccm.client_leader > 0) &&
10419                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
10420                 )
10421                {
10422                   if (!strncmp(str, "E_START|", 8))
10423                     {
10424                        int id;
10425
10426                        id = atoi(str + 8);
10427                        if (id > 0) bd->client.netwm.startup_id = id;
10428                     }
10429                   free(str);
10430                }
10431           }
10432         /* It's ok not to have fetch flag, should only be set on startup
10433          *     * and not changed. */
10434         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
10435           {
10436              if (bd->client.icccm.client_leader)
10437                {
10438                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
10439                     bd->client.netwm.pid = -1;
10440                }
10441              else
10442                bd->client.netwm.pid = -1;
10443           }
10444
10445         if (!bd->re_manage)
10446           {
10447              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
10448                                                         bd->client.netwm.pid);
10449              if ((inst) && (inst->used == 0))
10450                {
10451                   E_Zone *zone;
10452                   E_Desk *desk;
10453
10454                   inst->used++;
10455                   zone = e_container_zone_number_get(bd->zone->container,
10456                                                      inst->screen);
10457                   if (zone) e_border_zone_set(bd, zone);
10458                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
10459                                           inst->desk_y);
10460                   if (desk) e_border_desk_set(bd, desk);
10461                   e_exec_instance_found(inst);
10462                }
10463
10464              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
10465                {
10466                   E_Border *bdl = NULL;
10467
10468                   bdl = bd->parent;
10469                   if (!bdl)
10470                     {
10471                        if (bd->leader) bdl = bd->leader;
10472                     }
10473                   if (!bdl)
10474                     {
10475                        E_Border *child;
10476                        E_Border_List *bl;
10477
10478                        bl = e_container_border_list_first(bd->zone->container);
10479                        while ((child = e_container_border_list_next(bl)))
10480                          {
10481                             if (child == bd) continue;
10482                             if (e_object_is_del(E_OBJECT(child))) continue;
10483                             if ((bd->client.icccm.client_leader) &&
10484                                 (child->client.icccm.client_leader ==
10485                                     bd->client.icccm.client_leader))
10486                               {
10487                                  bdl = child;
10488                                  break;
10489                               }
10490                          }
10491                        e_container_border_list_free(bl);
10492                     }
10493                   if (bdl)
10494                     {
10495                        if (bdl->zone)
10496                          e_border_zone_set(bd, bdl->zone);
10497                        if (bdl->desk)
10498                          e_border_desk_set(bd, bdl->desk);
10499                        else
10500                          e_border_stick(bd);
10501                     }
10502                }
10503           }
10504      }
10505
10506 #ifdef _F_USE_DESK_WINDOW_PROFILE_
10507    if (need_desk_set)
10508      {
10509         E_Container *con = bd->zone->container;
10510         E_Desk *desk = NULL;
10511         Eina_List *l;
10512         const char *str;
10513         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
10514           {
10515              desk = e_container_desk_window_profile_get(con, str);
10516              if (desk)
10517                {
10518                   if (bd->desk != desk)
10519                     {
10520                        bd->client.e.state.profile = eina_stringshare_add(str);
10521                        if (bd->zone != desk->zone)
10522                          e_border_zone_set(bd, desk->zone);
10523                        e_border_desk_set(bd, desk);
10524                     }
10525                   break;
10526                }
10527           }
10528      }
10529 #endif
10530
10531    /* PRE_POST_FETCH calls e_remember apply for new client */
10532    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
10533    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
10534    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
10535
10536 #ifdef _F_ZONE_WINDOW_ROTATION_
10537    if (e_config->wm_win_rotation)
10538      {
10539         if ((need_rotation_set) &&
10540             (bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_NORMAL))
10541           {
10542              Eina_Bool hint = EINA_FALSE;
10543              int ang = 0;
10544              int x, y, w, h, move;
10545
10546              ELB(ELBT_ROT, "NEED ROT", bd->client.win);
10547              bd->client.e.state.rot.changes = _e_border_rotation_angle_get(bd);
10548
10549              if (bd->client.e.state.rot.changes == -1)
10550                {
10551                   ang = bd->client.e.state.rot.curr;
10552
10553                   hint = _e_border_rotation_geom_get(bd, bd->zone, ang, &x, &y, &w, &h, &move);
10554                   if (hint)
10555                     {
10556                        _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
10557                        ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
10558                             bd->client.icccm.name, x, y, w, h);
10559                     }
10560                }
10561              else bd->changed = 1;
10562           }
10563      }
10564 #endif
10565
10566    if (bd->need_reparent)
10567      {
10568         if (!bd->internal)
10569           ecore_x_window_save_set_add(bd->client.win);
10570         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
10571         if (bd->visible)
10572           {
10573              if ((bd->new_client) && (bd->internal) &&
10574                  (bd->internal_ecore_evas))
10575                ecore_evas_show(bd->internal_ecore_evas);
10576              ecore_x_window_show(bd->client.win);
10577           }
10578         bd->need_reparent = 0;
10579      }
10580
10581    if ((bd->client.border.changed) && (!bd->shaded) &&
10582        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10583      {
10584         const char *bordername;
10585
10586         if (bd->fullscreen)
10587           bordername = "borderless";
10588         else if (bd->bordername)
10589           bordername = bd->bordername;
10590         else if ((bd->client.mwm.borderless) || (bd->borderless))
10591           bordername = "borderless";
10592         else if (((bd->client.icccm.transient_for != 0) ||
10593                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
10594                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10595                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10596           bordername = "noresize_dialog";
10597         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10598                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10599           bordername = "noresize";
10600         else if (bd->client.shaped)
10601           bordername = "shaped";
10602         else if ((!bd->client.icccm.accepts_focus) &&
10603                  (!bd->client.icccm.take_focus))
10604           bordername = "nofocus";
10605         else if (bd->client.icccm.urgent)
10606           bordername = "urgent";
10607         else if ((bd->client.icccm.transient_for != 0) ||
10608                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10609           bordername = "dialog";
10610         else if (bd->client.netwm.state.modal)
10611           bordername = "modal";
10612         else if ((bd->client.netwm.state.skip_taskbar) ||
10613                  (bd->client.netwm.state.skip_pager))
10614           bordername = "skipped";
10615         else if ((bd->internal) && (bd->client.icccm.class) &&
10616                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
10617           bordername = "internal_fileman";
10618         else
10619           bordername = e_config->theme_default_border_style;
10620         if (!bordername) bordername = "default";
10621
10622         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
10623           {
10624              Evas_Object *o;
10625              char buf[4096];
10626              int ok;
10627
10628              bd->changes.border = 1;
10629              eina_stringshare_replace(&bd->client.border.name, bordername);
10630
10631              if (bd->bg_object)
10632                {
10633                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
10634                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
10635                   bd->changes.size = 1;
10636                   evas_object_del(bd->bg_object);
10637                }
10638              o = edje_object_add(bd->bg_evas);
10639              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
10640              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10641              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
10642                {
10643                   if (bd->client.border.name != e_config->theme_default_border_style)
10644                     {
10645                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
10646                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10647                     }
10648                   if (!ok)
10649                     {
10650                        ok = e_theme_edje_object_set(o, "base/theme/borders",
10651                                                     "e/widgets/border/default/border");
10652                        if (ok)
10653                          {
10654                             /* Reset default border style to default */
10655                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
10656                             e_config_save_queue();
10657                          }
10658                     }
10659                }
10660
10661              bd->shaped = 0;
10662              if (ok)
10663                {
10664                   const char *shape_option, *argb_option;
10665                   int use_argb = 0;
10666
10667                   bd->bg_object = o;
10668
10669                   if ((e_config->use_composite) && (!bd->client.argb))
10670                     {
10671                        argb_option = edje_object_data_get(o, "argb");
10672                        if ((argb_option) && (!strcmp(argb_option, "1")))
10673                          use_argb = 1;
10674
10675                        if (use_argb != bd->argb)
10676                          _e_border_frame_replace(bd, use_argb);
10677
10678                        o = bd->bg_object;
10679                     }
10680
10681                   if (!bd->argb)
10682                     {
10683                        shape_option = edje_object_data_get(o, "shaped");
10684                        if ((shape_option) && (!strcmp(shape_option, "1")))
10685                          bd->shaped = 1;
10686                     }
10687
10688                   if (bd->client.netwm.name)
10689                     edje_object_part_text_set(o, "e.text.title",
10690                                               bd->client.netwm.name);
10691                   else if (bd->client.icccm.title)
10692                     edje_object_part_text_set(o, "e.text.title",
10693                                               bd->client.icccm.title);
10694                }
10695              else
10696                {
10697                   evas_object_del(o);
10698                   bd->bg_object = NULL;
10699                }
10700
10701              _e_border_client_inset_calc(bd);
10702
10703              bd->w += (bd->client_inset.l + bd->client_inset.r);
10704              bd->h += (bd->client_inset.t + bd->client_inset.b);
10705              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
10706              bd->changes.size = 1;
10707              /*  really needed ? */
10708              ecore_x_window_move(bd->client.shell_win,
10709                                  bd->client_inset.l,
10710                                  bd->client_inset.t);
10711
10712              if (bd->maximized != E_MAXIMIZE_NONE)
10713                {
10714                   E_Maximize maximized = bd->maximized;
10715
10716                   /* to force possible resizes */
10717                   bd->maximized = E_MAXIMIZE_NONE;
10718
10719                   _e_border_maximize(bd, maximized);
10720
10721                   /* restore maximized state */
10722                   bd->maximized = maximized;
10723
10724                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
10725                                                bd->maximized & E_MAXIMIZE_VERTICAL);
10726                }
10727              if (bd->bg_object)
10728                {
10729                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
10730                                                   _e_border_cb_signal_bind, bd);
10731                   if (bd->focused)
10732                     {
10733                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
10734                        if (bd->icon_object)
10735                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10736                     }
10737                   if (bd->shaded)
10738                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
10739                   if (bd->sticky)
10740                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
10741                   if (bd->hung)
10742                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
10743                   // FIXME: in eval -do differently
10744                   //         edje_object_message_signal_process(bd->bg_object);
10745                   //         e_border_frame_recalc(bd);
10746
10747                   evas_object_move(bd->bg_object, 0, 0);
10748                   evas_object_resize(bd->bg_object, bd->w, bd->h);
10749                   evas_object_show(bd->bg_object);
10750                }
10751           }
10752         bd->client.border.changed = 0;
10753
10754         if (bd->icon_object)
10755           {
10756              if (bd->bg_object)
10757                {
10758                   evas_object_show(bd->icon_object);
10759                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10760                }
10761              else
10762                evas_object_hide(bd->icon_object);
10763           }
10764      }
10765
10766    if (rem_change) e_remember_update(bd);
10767
10768    if (change_urgent)
10769      {
10770         E_Event_Border_Urgent_Change *ev;
10771
10772         if (bd->client.icccm.urgent)
10773           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
10774         else
10775           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
10776
10777         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
10778         ev->border = bd;
10779         e_object_ref(E_OBJECT(bd));
10780         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
10781                         _e_border_event_border_urgent_change_free, NULL);
10782      }
10783
10784    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10785 }
10786
10787 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10788 static void
10789 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10790 {
10791    E_Border* temp_bd = NULL;
10792    E_Border* top_focusable_bd = NULL;
10793    Eina_Bool is_fully_obscured = EINA_FALSE;
10794    Ecore_X_XRegion *visible_region = NULL;
10795    Ecore_X_XRegion *win_region = NULL;
10796    Ecore_X_Rectangle visible_rect, win_rect;
10797    E_Border_List *bl;
10798
10799    // set the entire visible region as a root geometry
10800    visible_rect.x = bd->zone->x;
10801    visible_rect.y = bd->zone->y;
10802    visible_rect.width = bd->zone->w;
10803    visible_rect.height = bd->zone->h;
10804
10805    visible_region = ecore_x_xregion_new();
10806    if (!visible_region) return;
10807
10808    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10809
10810    bl = e_container_border_list_last(bd->zone->container);
10811    while ((temp_bd = e_container_border_list_prev(bl)))
10812      {
10813         if (temp_bd == bd) break;
10814
10815         if (temp_bd == focused) continue;
10816         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10817         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10818         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10819             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10820             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10821             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10822             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10823             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10824             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10825           {
10826              if (!top_focusable_bd)
10827                {
10828                   top_focusable_bd = temp_bd;
10829                }
10830
10831              win_rect.x = temp_bd->x;
10832              win_rect.y = temp_bd->y;
10833              win_rect.width = temp_bd->w;
10834              win_rect.height = temp_bd->h;
10835
10836              // if it stick out or is bigger than the entire visible region,
10837              // clip it by the entire visible's geometry.
10838              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10839                                   win_rect.width, win_rect.height,
10840                                   visible_rect.x, visible_rect.y,
10841                                   (int)(visible_rect.width), (int)(visible_rect.height));
10842
10843              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10844                {
10845                   win_region = ecore_x_xregion_new();
10846                   if (win_region)
10847                     {
10848                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10849                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10850                        ecore_x_xregion_free(win_region);
10851                        win_region = NULL;
10852
10853                        if (ecore_x_xregion_is_empty(visible_region))
10854                          {
10855                             is_fully_obscured = EINA_TRUE;
10856                             break;
10857                          }
10858                     }
10859                }
10860           }
10861      }
10862
10863    if (is_fully_obscured == EINA_TRUE)
10864      {
10865         e_border_focus_set(top_focusable_bd, 1, 1);
10866      }
10867    else
10868      {
10869         e_border_focus_set(bd, 1, 1);
10870      }
10871
10872    if (visible_region) ecore_x_xregion_free(visible_region);
10873    e_container_border_list_free(bl);
10874 }
10875
10876 static void
10877 _e_border_latest_stacked_focus(E_Border *bd)
10878 {
10879    E_Border *temp_bd;
10880    int root_w, root_h;
10881
10882    root_w = bd->zone->w;
10883    root_h = bd->zone->h;
10884
10885    Eina_List *l;
10886    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10887      {
10888         if (bd == temp_bd) continue;
10889         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10890         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10891
10892         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10893             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10894             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10895             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10896             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10897             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10898             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10899           {
10900              _e_border_latest_stacked_focus_check_set(temp_bd);
10901              break;
10902           }
10903      }
10904 }
10905
10906 static void
10907 _e_border_check_stack (E_Border *bd)
10908 {
10909    E_Border* temp_bd = NULL;
10910    E_Border* top_bd = NULL;
10911    int passed_focus = 0;
10912    int passed = 0;
10913    int root_w = bd->zone->w;
10914    int root_h = bd->zone->h;
10915
10916    E_Border_List *bl;
10917    bl = e_container_border_list_last(bd->zone->container);
10918    while ((temp_bd = e_container_border_list_prev(bl)))
10919      {
10920         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10921         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10922         if ((temp_bd != bd) &&
10923             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10924
10925         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10926            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10927            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10928            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10929            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10930            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10931            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10932           {
10933              if (bd == temp_bd)
10934                {
10935                   if (!passed)
10936                     {
10937                        e_border_focus_set_with_pointer(bd);
10938                        break;
10939                     }
10940                   else
10941                     {
10942                        if (!passed_focus)
10943                          {
10944                             e_border_focus_set_with_pointer(top_bd);
10945                          }
10946                        break;
10947                     }
10948                }
10949              else
10950                {
10951                   if (!passed)
10952                     {
10953                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10954                          {
10955                             if (!bd->lock_focus_out)
10956                               {
10957                                  e_border_focus_latest_set(bd);
10958                               }
10959                          }
10960                     }
10961                }
10962
10963              if (!passed)
10964                {
10965                   passed = 1;
10966                   top_bd = temp_bd;
10967                }
10968
10969              if (temp_bd == focused)
10970                {
10971                   passed_focus = 1;
10972                }
10973           }
10974      }
10975    e_container_border_list_free(bl);
10976 }
10977
10978 static void
10979 _e_border_focus_top_stack_set(E_Border* bd)
10980 {
10981    E_Border *temp_bd;
10982    int root_w, root_h;
10983
10984    root_w = bd->zone->w;
10985    root_h = bd->zone->h;
10986
10987    E_Border_List *bl;
10988    bl = e_container_border_list_last(bd->zone->container);
10989    while ((temp_bd = e_container_border_list_prev(bl)))
10990      {
10991         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10992         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10993         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
10994
10995         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10996            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10997            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10998            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10999            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
11000            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
11001            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
11002           {
11003              if (!temp_bd->focused)
11004                {
11005                   /* this border is the top of the latest stack */
11006                   e_border_focus_set (temp_bd, 1, 1);
11007                }
11008              break;
11009           }
11010      }
11011    e_container_border_list_free(bl);
11012 }
11013 #endif
11014
11015 static void
11016 _e_border_eval(E_Border *bd)
11017 {
11018    E_Event_Border_Property *event;
11019    E_Border_Pending_Move_Resize *pnd;
11020    int rem_change = 0;
11021    int send_event = 1;
11022
11023    if (e_object_is_del(E_OBJECT(bd)))
11024      {
11025         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
11026         bd->changed = 0;
11027         return;
11028      }
11029
11030    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
11031
11032    if (bd->new_client)
11033      {
11034         int zx = 0, zy = 0, zw = 0, zh = 0;
11035
11036         if (bd->zone)
11037           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
11038
11039         /*
11040          * Limit maximum size of windows to useful geometry
11041          */
11042         // TODO: temoporary limited maximize algorithm
11043         // ->
11044         /*if (bd->w > zw)
11045           rw = zw;
11046           else
11047           rw = bd->w;
11048
11049           if (bd->h > zh)
11050           rh = zh;
11051           else
11052           rh = bd->h;
11053
11054           if ((rw != bd->w) || (rh != bd->h))
11055           {
11056           bd->w = rw;
11057           bd->h = rh;
11058           e_border_resize (bd, bd->w, bd->h);
11059           }*/
11060         // <-
11061
11062         if (bd->re_manage)
11063           {
11064              bd->x -= bd->client_inset.l;
11065              bd->y -= bd->client_inset.t;
11066              bd->changes.pos = 1;
11067              bd->placed = 1;
11068           }
11069         else if ((!bd->placed) && (bd->client.icccm.request_pos))
11070           {
11071
11072              Ecore_X_Window_Attributes *att;
11073              int bw;
11074
11075              att = &bd->client.initial_attributes;
11076              bw = att->border * 2;
11077              switch (bd->client.icccm.gravity)
11078                {
11079                 case ECORE_X_GRAVITY_N:
11080                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
11081                    bd->y = att->y;
11082                    break;
11083
11084                 case ECORE_X_GRAVITY_NE:
11085                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
11086                    bd->y = att->y;
11087                    break;
11088
11089                 case ECORE_X_GRAVITY_E:
11090                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
11091                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
11092                    break;
11093
11094                 case ECORE_X_GRAVITY_SE:
11095                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
11096                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
11097                    break;
11098
11099                 case ECORE_X_GRAVITY_S:
11100                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
11101                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
11102                    break;
11103
11104                 case ECORE_X_GRAVITY_SW:
11105                    bd->x = att->x;
11106                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
11107                    break;
11108
11109                 case ECORE_X_GRAVITY_W:
11110                    bd->x = att->x;
11111                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
11112                    break;
11113
11114                 case ECORE_X_GRAVITY_CENTER:
11115                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
11116                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
11117                    break;
11118
11119                 case ECORE_X_GRAVITY_NW:
11120                 default:
11121                    bd->x = att->x;
11122                    bd->y = att->y;
11123                }
11124
11125              /*
11126               * This ensures that windows that like to open with a x/y
11127               * position smaller than returned by e_zone_useful_geometry_get()
11128               * are moved to useful positions.
11129               */
11130              // ->
11131              if (e_config->geometry_auto_move)
11132                {
11133                   if (bd->x < zx)
11134                     bd->x = zx;
11135
11136                   if (bd->y < zy)
11137                     bd->y = zy;
11138
11139                   if (bd->x + bd->w > zx + zw)
11140                     bd->x = zx + zw - bd->w;
11141
11142                   if (bd->y + bd->h > zy + zh)
11143                     bd->y = zy + zh - bd->h;
11144                   // <--
11145
11146                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
11147                     {
11148                        bd->changes.pos = 1;
11149                        bd->placed = 1;
11150                     }
11151                }
11152              else
11153                {
11154                   bd->changes.pos = 1;
11155                   bd->placed = 1;
11156                }
11157           }
11158         if (!bd->placed)
11159           {
11160              /* FIXME: special placement for dialogs etc. etc. etc goes
11161               * here */
11162              /* FIXME: what if parent is not on this desktop - or zone? */
11163              if ((bd->parent) && (bd->parent->visible))
11164                {
11165                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
11166                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
11167                   bd->changes.pos = 1;
11168                   bd->placed = 1;
11169                }
11170 #if 0
11171              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
11172                {
11173                   /* TODO: Place in center of group */
11174                }
11175 #endif
11176              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11177                {
11178                   bd->x = zx + ((zw - bd->w) / 2);
11179                   bd->y = zy + ((zh - bd->h) / 2);
11180                   bd->changes.pos = 1;
11181                   bd->placed = 1;
11182                }
11183           }
11184         if (!bd->placed)
11185           {
11186              Eina_List *skiplist = NULL;
11187              int new_x, new_y;
11188
11189              if (zw > bd->w)
11190                new_x = zx + (rand() % (zw - bd->w));
11191              else
11192                new_x = zx;
11193              if (zh > bd->h)
11194                new_y = zy + (rand() % (zh - bd->h));
11195              else
11196                new_y = zy;
11197
11198              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
11199                {
11200                   skiplist = eina_list_append(skiplist, bd);
11201                   if (bd->desk)
11202                     e_place_desk_region_smart(bd->desk, skiplist,
11203                                               bd->x, bd->y, bd->w, bd->h,
11204                                               &new_x, &new_y);
11205                   else
11206                     e_place_zone_region_smart(bd->zone, skiplist,
11207                                               bd->x, bd->y, bd->w, bd->h,
11208                                               &new_x, &new_y);
11209                   eina_list_free(skiplist);
11210                }
11211              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
11212                {
11213                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
11214                                       &new_x, &new_y);
11215                }
11216              else
11217                {
11218                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
11219                                       bd->client_inset.t, &new_x, &new_y);
11220                }
11221              bd->x = new_x;
11222              bd->y = new_y;
11223              bd->changes.pos = 1;
11224           }
11225
11226         EINA_LIST_FREE(bd->pending_move_resize, pnd)
11227           {
11228              if ((!bd->lock_client_location) && (pnd->move))
11229                {
11230                   bd->x = pnd->x;
11231                   bd->y = pnd->y;
11232                   bd->changes.pos = 1;
11233                   bd->placed = 1;
11234                   if (pnd->without_border)
11235                     {
11236                        bd->x -= bd->client_inset.l;
11237                        bd->y -= bd->client_inset.t;
11238                     }
11239                }
11240              if ((!bd->lock_client_size) && (pnd->resize))
11241                {
11242                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
11243                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
11244                   bd->client.w = pnd->w;
11245                   bd->client.h = pnd->h;
11246                   bd->changes.size = 1;
11247                }
11248
11249              free(pnd);
11250           }
11251
11252         /* Recreate state */
11253         e_hints_window_init(bd);
11254         if ((bd->client.e.state.centered) &&
11255             ((!bd->remember) ||
11256              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
11257           {
11258              bd->x = zx + (zw - bd->w) / 2;
11259              bd->y = zy + (zh - bd->h) / 2;
11260              bd->changes.pos = 1;
11261              bd->placed = 1;
11262           }
11263
11264         _e_border_client_move_resize_send(bd);
11265
11266         /* if the explicit geometry request asks for the app to be
11267          * in another zone - well move it there */
11268         {
11269            E_Zone *zone;
11270
11271            zone = e_container_zone_at_point_get(bd->zone->container,
11272                                                 bd->x + (bd->w / 2),
11273                                                 bd->y + (bd->h / 2));
11274            if (!zone)
11275              zone = e_container_zone_at_point_get(bd->zone->container,
11276                                                   bd->x,
11277                                                   bd->y);
11278            if (!zone)
11279              zone = e_container_zone_at_point_get(bd->zone->container,
11280                                                   bd->x + bd->w - 1,
11281                                                   bd->y);
11282            if (!zone)
11283              zone = e_container_zone_at_point_get(bd->zone->container,
11284                                                   bd->x + bd->w - 1,
11285                                                   bd->y + bd->h - 1);
11286            if (!zone)
11287              zone = e_container_zone_at_point_get(bd->zone->container,
11288                                                   bd->x,
11289                                                   bd->y + bd->h - 1);
11290            if ((zone) && (zone != bd->zone))
11291              e_border_zone_set(bd, zone);
11292         }
11293      }
11294
11295    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
11296
11297    /* effect changes to the window border itself */
11298    if ((bd->changes.shading))
11299      {
11300         /*  show at start of unshade (but don't hide until end of shade) */
11301         if (bd->shaded)
11302           ecore_x_window_raise(bd->client.shell_win);
11303         bd->changes.shading = 0;
11304         rem_change = 1;
11305      }
11306    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
11307      {
11308         if (bd->shaded)
11309           ecore_x_window_lower(bd->client.shell_win);
11310         else
11311           ecore_x_window_raise(bd->client.shell_win);
11312         bd->changes.shaded = 0;
11313         rem_change = 1;
11314      }
11315    else if ((bd->changes.shaded) && (bd->changes.pos))
11316      {
11317         if (bd->shaded)
11318           ecore_x_window_lower(bd->client.shell_win);
11319         else
11320           ecore_x_window_raise(bd->client.shell_win);
11321         bd->changes.size = 1;
11322         bd->changes.shaded = 0;
11323         rem_change = 1;
11324      }
11325    else if ((bd->changes.shaded) && (bd->changes.size))
11326      {
11327         if (bd->shaded)
11328           ecore_x_window_lower(bd->client.shell_win);
11329         else
11330           ecore_x_window_raise(bd->client.shell_win);
11331         bd->changes.shaded = 0;
11332         rem_change = 1;
11333      }
11334    else if (bd->changes.shaded)
11335      {
11336         if (bd->shaded)
11337           ecore_x_window_lower(bd->client.shell_win);
11338         else
11339           ecore_x_window_raise(bd->client.shell_win);
11340         bd->changes.size = 1;
11341         bd->changes.shaded = 0;
11342         rem_change = 1;
11343      }
11344
11345    if (bd->changes.size)
11346      {
11347         int x = 0, y = 0, xx = 0, yy = 0;
11348
11349         if ((bd->shaded) && (!bd->shading))
11350           {
11351              evas_obscured_clear(bd->bg_evas);
11352           }
11353         else
11354           {
11355              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
11356              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
11357
11358              evas_obscured_clear(bd->bg_evas);
11359              evas_obscured_rectangle_add(bd->bg_evas,
11360                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
11361
11362              if (bd->shading)
11363                {
11364                   if (bd->shade.dir == E_DIRECTION_UP)
11365                     {
11366                        y = yy - bd->client.h;
11367                     }
11368                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11369                     {
11370                        x = xx - bd->client.w;
11371                     }
11372                }
11373           }
11374
11375         if (bd->client.e.state.video)
11376           {
11377              if (bd->client.e.state.video_position.updated)
11378                {
11379                   ecore_x_window_move(bd->win,
11380                                       bd->client.e.state.video_parent_border->x +
11381                                       bd->client.e.state.video_parent_border->client_inset.l +
11382                                       bd->client.e.state.video_parent_border->fx.x +
11383                                       bd->client.e.state.video_position.x,
11384                                       bd->client.e.state.video_parent_border->y +
11385                                       bd->client.e.state.video_parent_border->client_inset.t +
11386                                       bd->client.e.state.video_parent_border->fx.y +
11387                                       bd->client.e.state.video_position.y);
11388                   bd->client.e.state.video_position.updated = 0;
11389                }
11390           }
11391         else if (!bd->changes.pos)
11392           {
11393              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11394              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11395              bd->post_resize = 1;
11396           }
11397         else
11398           {
11399              E_Border *tmp;
11400              Eina_List *l;
11401
11402              ecore_x_window_move_resize(bd->win,
11403                                         bd->x + bd->fx.x,
11404                                         bd->y + bd->fx.y,
11405                                         bd->w, bd->h);
11406
11407              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
11408                ecore_x_window_move(tmp->win,
11409                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
11410                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
11411           }
11412
11413         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
11414
11415         if ((!bd->shaded) || (bd->shading))
11416           ecore_x_window_move_resize(bd->client.shell_win,
11417                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
11418
11419         if (bd->internal_ecore_evas)
11420           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
11421         else if (!bd->client.e.state.video)
11422           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
11423
11424         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
11425         evas_object_resize(bd->bg_object, bd->w, bd->h);
11426         e_container_shape_resize(bd->shape, bd->w, bd->h);
11427         if (bd->changes.pos)
11428           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11429
11430         _e_border_client_move_resize_send(bd);
11431
11432         bd->changes.pos = 0;
11433         bd->changes.size = 0;
11434         rem_change = 1;
11435      }
11436    else if (bd->changes.pos)
11437      {
11438         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11439         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11440         bd->post_move = 1;
11441
11442         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11443
11444         _e_border_client_move_resize_send(bd);
11445
11446         bd->changes.pos = 0;
11447         rem_change = 1;
11448      }
11449
11450    if (bd->changes.reset_gravity)
11451      {
11452         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
11453         bd->changes.reset_gravity = 0;
11454         rem_change = 1;
11455      }
11456
11457    if (bd->need_shape_merge)
11458      {
11459         _e_border_shape_input_rectangle_set(bd);
11460         if ((bd->shaped) || (bd->client.shaped))
11461           {
11462              Ecore_X_Window twin, twin2;
11463              int x, y;
11464
11465              twin = ecore_x_window_override_new
11466                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
11467              if (bd->shaped)
11468                ecore_x_window_shape_window_set(twin, bd->bg_win);
11469              else
11470                {
11471                   Ecore_X_Rectangle rects[4];
11472
11473                   rects[0].x = 0;
11474                   rects[0].y = 0;
11475                   rects[0].width = bd->w;
11476                   rects[0].height = bd->client_inset.t;
11477                   rects[1].x = 0;
11478                   rects[1].y = bd->client_inset.t;
11479                   rects[1].width = bd->client_inset.l;
11480                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11481                   rects[2].x = bd->w - bd->client_inset.r;
11482                   rects[2].y = bd->client_inset.t;
11483                   rects[2].width = bd->client_inset.r;
11484                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11485                   rects[3].x = 0;
11486                   rects[3].y = bd->h - bd->client_inset.b;
11487                   rects[3].width = bd->w;
11488                   rects[3].height = bd->client_inset.b;
11489                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
11490                }
11491              twin2 = ecore_x_window_override_new
11492                (bd->zone->container->scratch_win, 0, 0,
11493                 bd->w - bd->client_inset.l - bd->client_inset.r,
11494                 bd->h - bd->client_inset.t - bd->client_inset.b);
11495              x = 0;
11496              y = 0;
11497              if ((bd->shading) || (bd->shaded))
11498                {
11499                   if (bd->shade.dir == E_DIRECTION_UP)
11500                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
11501                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11502                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
11503                }
11504              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
11505                                                 x, y);
11506              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
11507                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
11508                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
11509              ecore_x_window_shape_window_add_xy(twin, twin2,
11510                                                 bd->client_inset.l,
11511                                                 bd->client_inset.t);
11512              ecore_x_window_free(twin2);
11513              ecore_x_window_shape_window_set(bd->win, twin);
11514              ecore_x_window_free(twin);
11515           }
11516         else
11517           ecore_x_window_shape_mask_set(bd->win, 0);
11518         //      bd->need_shape_export = 1;
11519         bd->need_shape_merge = 0;
11520      }
11521
11522    if (bd->need_shape_export)
11523      {
11524         Ecore_X_Rectangle *rects, *orects;
11525         int num;
11526
11527         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
11528         if (rects)
11529           {
11530              int changed;
11531
11532              changed = 1;
11533              if ((num == bd->shape_rects_num) && (bd->shape_rects))
11534                {
11535                   int i;
11536
11537                   orects = bd->shape_rects;
11538                   changed = 0;
11539                   for (i = 0; i < num; i++)
11540                     {
11541                        if (rects[i].x < 0)
11542                          {
11543                             rects[i].width -= rects[i].x;
11544                             rects[i].x = 0;
11545                          }
11546                        if ((rects[i].x + (int)rects[i].width) > bd->w)
11547                          rects[i].width = rects[i].width - rects[i].x;
11548                        if (rects[i].y < 0)
11549                          {
11550                             rects[i].height -= rects[i].y;
11551                             rects[i].y = 0;
11552                          }
11553                        if ((rects[i].y + (int)rects[i].height) > bd->h)
11554                          rects[i].height = rects[i].height - rects[i].y;
11555
11556                        if ((orects[i].x != rects[i].x) ||
11557                            (orects[i].y != rects[i].y) ||
11558                            (orects[i].width != rects[i].width) ||
11559                            (orects[i].height != rects[i].height))
11560                          {
11561                             changed = 1;
11562                             break;
11563                          }
11564                     }
11565                }
11566              if (changed)
11567                {
11568                   if (bd->client.shaped)
11569                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
11570                   else
11571                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
11572                   E_FREE(bd->shape_rects);
11573                   bd->shape_rects = rects;
11574                   bd->shape_rects_num = num;
11575                   e_container_shape_rects_set(bd->shape, rects, num);
11576                }
11577              else
11578                free(rects);
11579           }
11580         else
11581           {
11582              E_FREE(bd->shape_rects);
11583              bd->shape_rects = NULL;
11584              bd->shape_rects_num = 0;
11585              e_container_shape_rects_set(bd->shape, NULL, 0);
11586           }
11587         bd->need_shape_export = 0;
11588      }
11589
11590    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
11591      {
11592         int x, y;
11593
11594         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
11595         if ((!bd->placed) && (!bd->re_manage) &&
11596             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
11597             (!((bd->client.icccm.transient_for != 0) ||
11598                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
11599             (!bdmove) && (!bdresize))
11600           {
11601              /* Set this window into moving state */
11602
11603              bd->cur_mouse_action = e_action_find("window_move");
11604              if (bd->cur_mouse_action)
11605                {
11606                   if ((!bd->cur_mouse_action->func.end_mouse) &&
11607                       (!bd->cur_mouse_action->func.end))
11608                     bd->cur_mouse_action = NULL;
11609                   if (bd->cur_mouse_action)
11610                     {
11611                        bd->x = x - (bd->w >> 1);
11612                        bd->y = y - (bd->client_inset.t >> 1);
11613                        bd->changed = 1;
11614                        bd->changes.pos = 1;
11615
11616                        _e_border_client_move_resize_send(bd);
11617                     }
11618                }
11619           }
11620
11621         _e_border_show(bd);
11622
11623         if (bd->cur_mouse_action)
11624           {
11625              bd->moveinfo.down.x = bd->x + bd->fx.x;
11626              bd->moveinfo.down.y = bd->y + bd->fx.y;
11627              bd->moveinfo.down.w = bd->w;
11628              bd->moveinfo.down.h = bd->h;
11629              bd->mouse.current.mx = x;
11630              bd->mouse.current.my = y;
11631              bd->moveinfo.down.button = 0;
11632              bd->moveinfo.down.mx = x;
11633              bd->moveinfo.down.my = y;
11634
11635              grabbed = 1;
11636              e_object_ref(E_OBJECT(bd->cur_mouse_action));
11637              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
11638              if (e_config->border_raise_on_mouse_action)
11639                e_border_raise(bd);
11640              e_border_focus_set(bd, 1, 1);
11641           }
11642         bd->changes.visible = 0;
11643         rem_change = 1;
11644      }
11645
11646    if (bd->changes.icon)
11647      {
11648         if (bd->desktop)
11649           {
11650              efreet_desktop_free(bd->desktop);
11651              bd->desktop = NULL;
11652           }
11653         if (bd->icon_object)
11654           {
11655              evas_object_del(bd->icon_object);
11656              bd->icon_object = NULL;
11657           }
11658         if (bd->remember && bd->remember->prop.desktop_file)
11659           {
11660              const char *desktop = bd->remember->prop.desktop_file;
11661
11662              bd->desktop = efreet_desktop_get(desktop);
11663              if (!bd->desktop)
11664                bd->desktop = efreet_util_desktop_name_find(desktop);
11665           }
11666         if (!bd->desktop)
11667           {
11668              if ((bd->client.icccm.name) && (bd->client.icccm.class))
11669                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
11670                                                                bd->client.icccm.class);
11671           }
11672         if (!bd->desktop)
11673           {
11674              /* libreoffice and maybe others match window class
11675                 with .desktop file name */
11676              if (bd->client.icccm.class)
11677                {
11678                   char buf[128];
11679                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
11680                   bd->desktop = efreet_util_desktop_file_id_find(buf);
11681                }
11682           }
11683         if (!bd->desktop)
11684           {
11685              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
11686                                                       bd->client.netwm.pid);
11687              if (bd->desktop) efreet_desktop_ref(bd->desktop);
11688           }
11689         if (!bd->desktop && bd->client.icccm.name)
11690           {
11691              /* this works for most cases as fallback. useful when app is
11692                 run from a shell  */
11693              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
11694           }
11695         if (!bd->desktop && bd->client.icccm.transient_for)
11696           {
11697              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
11698              if (bd2 && bd2->desktop)
11699                {
11700                   efreet_desktop_ref(bd2->desktop);
11701                   bd->desktop = bd2->desktop;
11702                }
11703           }
11704         if (bd->desktop)
11705           {
11706              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
11707                                             bd->desktop->orig_path);
11708           }
11709
11710         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
11711         if ((bd->focused) && (bd->icon_object))
11712           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
11713         if (bd->bg_object)
11714           {
11715              evas_object_show(bd->icon_object);
11716              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
11717           }
11718         else
11719           evas_object_hide(bd->icon_object);
11720
11721         {
11722            E_Event_Border_Icon_Change *ev;
11723
11724            ev = E_NEW(E_Event_Border_Icon_Change, 1);
11725            ev->border = bd;
11726            e_object_ref(E_OBJECT(bd));
11727            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
11728            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
11729                            _e_border_event_border_icon_change_free, NULL);
11730         }
11731         bd->changes.icon = 0;
11732      }
11733
11734    bd->new_client = 0;
11735    bd->changed = 0;
11736    bd->changes.stack = 0;
11737    bd->changes.prop = 0;
11738
11739    if (bd->client.e.state.rot.changes != -1)
11740      {
11741         e_border_rotation_set(bd, bd->client.e.state.rot.changes);
11742         bd->client.e.state.rot.changes = -1;
11743      }
11744
11745    if ((bd->take_focus) || (bd->want_focus))
11746      {
11747         bd->take_focus = 0;
11748 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11749         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
11750             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
11751             (bd->want_focus))
11752 #else // original
11753         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
11754 #endif
11755           {
11756              bd->want_focus = 0;
11757 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11758              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
11759                 _e_border_check_stack(bd);
11760              else
11761 #endif
11762              e_border_focus_set_with_pointer(bd);
11763           }
11764         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11765           {
11766              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
11767                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
11768                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
11769                    e_border_focused_get())))
11770                {
11771                   e_border_focus_set_with_pointer(bd);
11772                }
11773           }
11774         else
11775           {
11776              /* focus window by default when it is the only one on desk */
11777              E_Border *bd2 = NULL;
11778              Eina_List *l;
11779              EINA_LIST_FOREACH(focus_stack, l, bd2)
11780                {
11781                   if (bd == bd2) continue;
11782                   if ((!bd2->iconic) && (bd2->visible) &&
11783                       ((bd->desk == bd2->desk) || bd2->sticky))
11784                     break;
11785                }
11786
11787              if (!bd2)
11788                {
11789                   e_border_focus_set_with_pointer(bd);
11790                }
11791           }
11792      }
11793
11794    if (bd->need_maximize)
11795      {
11796         E_Maximize max;
11797         max = bd->maximized;
11798         bd->maximized = E_MAXIMIZE_NONE;
11799         e_border_maximize(bd, max);
11800         bd->need_maximize = 0;
11801      }
11802
11803    if (bd->need_fullscreen)
11804      {
11805         e_border_fullscreen(bd, e_config->fullscreen_policy);
11806         bd->need_fullscreen = 0;
11807      }
11808
11809    if (rem_change)
11810      e_remember_update(bd);
11811
11812    if (send_event) // FIXME: send only if a property changed - above need to
11813      { // check on that. for now - always send.
11814         event = E_NEW(E_Event_Border_Property, 1);
11815         event->border = bd;
11816         e_object_ref(E_OBJECT(bd));
11817         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11818      }
11819    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11820 }
11821
11822 static void
11823 _e_border_moveinfo_gather(E_Border   *bd,
11824                           const char *source)
11825 {
11826    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11827    else if (e_util_glob_match(source, "mouse,*,2"))
11828      bd->moveinfo.down.button = 2;
11829    else if (e_util_glob_match(source, "mouse,*,3"))
11830      bd->moveinfo.down.button = 3;
11831    else bd->moveinfo.down.button = 0;
11832    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11833      {
11834         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11835         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11836      }
11837    else
11838      {
11839         bd->moveinfo.down.mx = bd->mouse.current.mx;
11840         bd->moveinfo.down.my = bd->mouse.current.my;
11841      }
11842 }
11843
11844 static void
11845 _e_border_resize_handle(E_Border *bd)
11846 {
11847    int x, y, w, h;
11848    int new_x, new_y, new_w, new_h;
11849    int tw, th;
11850    Eina_List *skiplist = NULL;
11851
11852    x = bd->x;
11853    y = bd->y;
11854    w = bd->w;
11855    h = bd->h;
11856
11857    if ((bd->resize_mode == RESIZE_TR) ||
11858        (bd->resize_mode == RESIZE_R) ||
11859        (bd->resize_mode == RESIZE_BR))
11860      {
11861         if ((bd->moveinfo.down.button >= 1) &&
11862             (bd->moveinfo.down.button <= 3))
11863           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11864             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11865         else
11866           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11867      }
11868    else if ((bd->resize_mode == RESIZE_TL) ||
11869             (bd->resize_mode == RESIZE_L) ||
11870             (bd->resize_mode == RESIZE_BL))
11871      {
11872         if ((bd->moveinfo.down.button >= 1) &&
11873             (bd->moveinfo.down.button <= 3))
11874           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11875             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11876         else
11877           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11878      }
11879
11880    if ((bd->resize_mode == RESIZE_TL) ||
11881        (bd->resize_mode == RESIZE_T) ||
11882        (bd->resize_mode == RESIZE_TR))
11883      {
11884         if ((bd->moveinfo.down.button >= 1) &&
11885             (bd->moveinfo.down.button <= 3))
11886           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11887             (bd->mouse.current.my - bd->moveinfo.down.my);
11888         else
11889           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11890      }
11891    else if ((bd->resize_mode == RESIZE_BL) ||
11892             (bd->resize_mode == RESIZE_B) ||
11893             (bd->resize_mode == RESIZE_BR))
11894      {
11895         if ((bd->moveinfo.down.button >= 1) &&
11896             (bd->moveinfo.down.button <= 3))
11897           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11898             (bd->mouse.current.my - bd->moveinfo.down.my);
11899         else
11900           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11901      }
11902
11903    tw = bd->w;
11904    th = bd->h;
11905
11906    if ((bd->resize_mode == RESIZE_TL) ||
11907        (bd->resize_mode == RESIZE_L) ||
11908        (bd->resize_mode == RESIZE_BL))
11909      x += (tw - w);
11910    if ((bd->resize_mode == RESIZE_TL) ||
11911        (bd->resize_mode == RESIZE_T) ||
11912        (bd->resize_mode == RESIZE_TR))
11913      y += (th - h);
11914
11915    skiplist = eina_list_append(skiplist, bd);
11916    e_resist_container_border_position(bd->zone->container, skiplist,
11917                                       bd->x, bd->y, bd->w, bd->h,
11918                                       x, y, w, h,
11919                                       &new_x, &new_y, &new_w, &new_h);
11920    eina_list_free(skiplist);
11921
11922    w = new_w;
11923    h = new_h;
11924    e_border_resize_limit(bd, &new_w, &new_h);
11925    if ((bd->resize_mode == RESIZE_TL) ||
11926        (bd->resize_mode == RESIZE_L) ||
11927        (bd->resize_mode == RESIZE_BL))
11928      new_x += (w - new_w);
11929    if ((bd->resize_mode == RESIZE_TL) ||
11930        (bd->resize_mode == RESIZE_T) ||
11931        (bd->resize_mode == RESIZE_TR))
11932      new_y += (h - new_h);
11933
11934    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11935 }
11936
11937 static Eina_Bool
11938 _e_border_shade_animator(void *data)
11939 {
11940    E_Border *bd = data;
11941    double dt, val;
11942    double dur = bd->client.h / e_config->border_shade_speed;
11943
11944    dt = ecore_loop_time_get() - bd->shade.start;
11945    val = dt / dur;
11946
11947    if (val < 0.0) val = 0.0;
11948    else if (val > 1.0) val = 1.0;
11949
11950    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11951      {
11952         bd->shade.val =
11953            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
11954         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11955      }
11956    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
11957      {
11958         bd->shade.val =
11959            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
11960         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11961      }
11962    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
11963      {
11964         bd->shade.val =
11965            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
11966         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11967      }
11968    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
11969      {
11970         bd->shade.val =
11971            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 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_ACCELERATE_LOTS)
11975      {
11976         bd->shade.val =
11977            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 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_DECELERATE_LOTS)
11981      {
11982         bd->shade.val =
11983            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 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_SINUSOIDAL_LOTS)
11987      {
11988         bd->shade.val =
11989            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 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_BOUNCE)
11993      {
11994         bd->shade.val =
11995            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
11996         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11997      }
11998    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
11999      {
12000         bd->shade.val =
12001            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
12002         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
12003      }
12004    else
12005      {
12006         bd->shade.val =
12007            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
12008         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
12009      }
12010
12011    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
12012    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
12013    else if (bd->shade.val > .999)
12014      bd->shade.val = 1.0;
12015
12016    if (bd->shade.dir == E_DIRECTION_UP)
12017      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
12018    else if (bd->shade.dir == E_DIRECTION_DOWN)
12019      {
12020         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
12021         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
12022         bd->changes.pos = 1;
12023      }
12024    else if (bd->shade.dir == E_DIRECTION_LEFT)
12025      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
12026    else if (bd->shade.dir == E_DIRECTION_RIGHT)
12027      {
12028         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
12029         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
12030         bd->changes.pos = 1;
12031      }
12032
12033    if ((bd->shaped) || (bd->client.shaped))
12034      {
12035         bd->need_shape_merge = 1;
12036         bd->need_shape_export = 1;
12037      }
12038    if (bd->shaped_input)
12039      {
12040         bd->need_shape_merge = 1;
12041      }
12042    bd->changes.size = 1;
12043    bd->changed = 1;
12044
12045    /* we're done */
12046    if (val == 1)
12047      {
12048         E_Event_Border_Resize *ev;
12049
12050         bd->shading = 0;
12051         bd->shaded = !(bd->shaded);
12052         bd->changes.size = 1;
12053         bd->changes.shaded = 1;
12054         bd->changes.shading = 1;
12055         bd->changed = 1;
12056         bd->shade.anim = NULL;
12057
12058         if (bd->shaded)
12059           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
12060         else
12061           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
12062         edje_object_message_signal_process(bd->bg_object);
12063         e_border_frame_recalc(bd);
12064
12065         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
12066         ev = E_NEW(E_Event_Border_Resize, 1);
12067         ev->border = bd;
12068         e_object_ref(E_OBJECT(bd));
12069 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
12070         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
12071         return ECORE_CALLBACK_CANCEL;
12072      }
12073    return ECORE_CALLBACK_RENEW;
12074 }
12075
12076 static void
12077 _e_border_event_border_resize_free(void *data __UNUSED__,
12078                                    void      *ev)
12079 {
12080    E_Event_Border_Resize *e;
12081
12082    e = ev;
12083 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
12084    e_object_unref(E_OBJECT(e->border));
12085    E_FREE(e);
12086 }
12087
12088 static void
12089 _e_border_event_border_move_free(void *data __UNUSED__,
12090                                  void      *ev)
12091 {
12092    E_Event_Border_Move *e;
12093
12094    e = ev;
12095 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
12096    e_object_unref(E_OBJECT(e->border));
12097    E_FREE(e);
12098 }
12099
12100 static void
12101 _e_border_event_border_add_free(void *data __UNUSED__,
12102                                 void      *ev)
12103 {
12104    E_Event_Border_Add *e;
12105
12106    e = ev;
12107 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
12108    e_object_unref(E_OBJECT(e->border));
12109    E_FREE(e);
12110 }
12111
12112 static void
12113 _e_border_event_border_remove_free(void *data __UNUSED__,
12114                                    void      *ev)
12115 {
12116    E_Event_Border_Remove *e;
12117
12118    e = ev;
12119 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
12120    e_object_unref(E_OBJECT(e->border));
12121    E_FREE(e);
12122 }
12123
12124 static void
12125 _e_border_event_border_show_free(void *data __UNUSED__,
12126                                  void      *ev)
12127 {
12128    E_Event_Border_Show *e;
12129
12130    e = ev;
12131 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
12132    e_object_unref(E_OBJECT(e->border));
12133    E_FREE(e);
12134 }
12135
12136 static void
12137 _e_border_event_border_hide_free(void *data __UNUSED__,
12138                                  void      *ev)
12139 {
12140    E_Event_Border_Hide *e;
12141
12142    e = ev;
12143 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
12144    e_object_unref(E_OBJECT(e->border));
12145    E_FREE(e);
12146 }
12147
12148 static void
12149 _e_border_event_border_iconify_free(void *data __UNUSED__,
12150                                     void      *ev)
12151 {
12152    E_Event_Border_Iconify *e;
12153
12154    e = ev;
12155 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
12156    e_object_unref(E_OBJECT(e->border));
12157    E_FREE(e);
12158 }
12159
12160 static void
12161 _e_border_event_border_uniconify_free(void *data __UNUSED__,
12162                                       void      *ev)
12163 {
12164    E_Event_Border_Uniconify *e;
12165
12166    e = ev;
12167 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
12168    e_object_unref(E_OBJECT(e->border));
12169    E_FREE(e);
12170 }
12171
12172 static void
12173 _e_border_event_border_stick_free(void *data __UNUSED__,
12174                                   void      *ev)
12175 {
12176    E_Event_Border_Stick *e;
12177
12178    e = ev;
12179 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
12180    e_object_unref(E_OBJECT(e->border));
12181    E_FREE(e);
12182 }
12183
12184 static void
12185 _e_border_event_border_unstick_free(void *data __UNUSED__,
12186                                     void      *ev)
12187 {
12188    E_Event_Border_Unstick *e;
12189
12190    e = ev;
12191 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
12192    e_object_unref(E_OBJECT(e->border));
12193    E_FREE(e);
12194 }
12195
12196 static void
12197 _e_border_event_border_zone_set_free(void *data __UNUSED__,
12198                                      void      *ev)
12199 {
12200    E_Event_Border_Zone_Set *e;
12201
12202    e = ev;
12203 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
12204    e_object_unref(E_OBJECT(e->border));
12205    e_object_unref(E_OBJECT(e->zone));
12206    E_FREE(e);
12207 }
12208
12209 static void
12210 _e_border_event_border_desk_set_free(void *data __UNUSED__,
12211                                      void      *ev)
12212 {
12213    E_Event_Border_Desk_Set *e;
12214
12215    e = ev;
12216 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
12217    e_object_unref(E_OBJECT(e->border));
12218    e_object_unref(E_OBJECT(e->desk));
12219    E_FREE(e);
12220 }
12221
12222 static void
12223 _e_border_event_border_stack_free(void *data __UNUSED__,
12224                                   void      *ev)
12225 {
12226    E_Event_Border_Stack *e;
12227
12228    e = ev;
12229 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
12230    e_object_unref(E_OBJECT(e->border));
12231    if (e->stack)
12232      {
12233 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
12234           e_object_unref(E_OBJECT(e->stack));
12235      }
12236    E_FREE(e);
12237 }
12238
12239 static void
12240 _e_border_event_border_icon_change_free(void *data __UNUSED__,
12241                                         void      *ev)
12242 {
12243    E_Event_Border_Icon_Change *e;
12244
12245    e = ev;
12246 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
12247    e_object_unref(E_OBJECT(e->border));
12248    E_FREE(e);
12249 }
12250
12251 static void
12252 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
12253                                           void      *ev)
12254 {
12255    E_Event_Border_Urgent_Change *e;
12256
12257    e = ev;
12258    e_object_unref(E_OBJECT(e->border));
12259    E_FREE(e);
12260 }
12261
12262 static void
12263 _e_border_event_border_focus_in_free(void *data __UNUSED__,
12264                                      void      *ev)
12265 {
12266    E_Event_Border_Focus_In *e;
12267
12268    e = ev;
12269    e_object_unref(E_OBJECT(e->border));
12270    E_FREE(e);
12271 }
12272
12273 static void
12274 _e_border_event_border_focus_out_free(void *data __UNUSED__,
12275                                       void      *ev)
12276 {
12277    E_Event_Border_Focus_Out *e;
12278
12279    e = ev;
12280    e_object_unref(E_OBJECT(e->border));
12281    E_FREE(e);
12282 }
12283
12284 static void
12285 _e_border_event_border_property_free(void *data __UNUSED__,
12286                                      void      *ev)
12287 {
12288    E_Event_Border_Property *e;
12289
12290    e = ev;
12291    e_object_unref(E_OBJECT(e->border));
12292    E_FREE(e);
12293 }
12294
12295 static void
12296 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
12297                                        void      *ev)
12298 {
12299    E_Event_Border_Fullscreen *e;
12300
12301    e = ev;
12302 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
12303    e_object_unref(E_OBJECT(e->border));
12304    E_FREE(e);
12305 }
12306
12307 static void
12308 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
12309                                          void      *ev)
12310 {
12311    E_Event_Border_Unfullscreen *e;
12312
12313    e = ev;
12314 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
12315    e_object_unref(E_OBJECT(e->border));
12316    E_FREE(e);
12317 }
12318
12319 #ifdef _F_ZONE_WINDOW_ROTATION_
12320 static void
12321 _e_border_event_border_rotation_change_begin_free(void *data __UNUSED__,
12322                                                   void      *ev)
12323 {
12324    E_Event_Border_Rotation_Change_Begin *e;
12325    e = ev;
12326    e_object_unref(E_OBJECT(e->border));
12327    E_FREE(e);
12328 }
12329
12330 static void
12331 _e_border_event_border_rotation_change_cancel_free(void *data __UNUSED__,
12332                                                    void      *ev)
12333 {
12334    E_Event_Border_Rotation_Change_Cancel *e;
12335    e = ev;
12336    e_object_unref(E_OBJECT(e->border));
12337    E_FREE(e);
12338 }
12339
12340 static void
12341 _e_border_event_border_rotation_change_end_free(void *data __UNUSED__,
12342                                                 void      *ev)
12343 {
12344    E_Event_Border_Rotation_Change_End *e;
12345    e = ev;
12346    e_object_unref(E_OBJECT(e->border));
12347    E_FREE(e);
12348 }
12349
12350 static void
12351 _e_border_event_border_rotation_change_begin_send(E_Border *bd)
12352 {
12353    E_Event_Border_Rotation_Change_Begin *ev = NULL;
12354    ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
12355    if (ev)
12356      {
12357         ev->border = bd;
12358         e_object_ref(E_OBJECT(bd));
12359         ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_BEGIN,
12360                         ev,
12361                         _e_border_event_border_rotation_change_begin_free,
12362                         NULL);
12363      }
12364 }
12365 #endif
12366
12367 static void
12368 _e_border_zone_update(E_Border *bd)
12369 {
12370    E_Container *con;
12371    Eina_List *l;
12372    E_Zone *zone;
12373
12374    /* still within old zone - leave it there */
12375    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12376                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
12377 #if _F_BORDER_CLIP_TO_ZONE_
12378      {
12379         _e_border_shape_input_clip_to_zone(bd);
12380         return;
12381      }
12382 #else
12383      return;
12384 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12385    /* find a new zone */
12386    con = bd->zone->container;
12387    EINA_LIST_FOREACH(con->zones, l, zone)
12388      {
12389         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12390                          zone->x, zone->y, zone->w, zone->h))
12391           {
12392              e_border_zone_set(bd, zone);
12393 #if _F_BORDER_CLIP_TO_ZONE_
12394              _e_border_shape_input_clip_to_zone(bd);
12395 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12396              return;
12397           }
12398      }
12399 }
12400
12401 static int
12402 _e_border_resize_begin(E_Border *bd)
12403 {
12404    int ret;
12405
12406    if (!bd->lock_user_stacking)
12407      {
12408         if (e_config->border_raise_on_mouse_action)
12409           e_border_raise(bd);
12410      }
12411    if ((bd->shaded) || (bd->shading) ||
12412        (bd->fullscreen) || (bd->lock_user_size))
12413      return 0;
12414
12415    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12416      ret = e_grabinput_get(bd->win, 0, bd->win);
12417    else
12418      ret = e_grabinput_get(bd->win, 0, 0);
12419
12420    if (grabbed && !ret)
12421      {
12422         grabbed = 0;
12423         return 0;
12424      }
12425
12426    if (bd->client.netwm.sync.request)
12427      {
12428         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12429         bd->client.netwm.sync.serial = 1;
12430         bd->client.netwm.sync.wait = 0;
12431         bd->client.netwm.sync.send_time = ecore_loop_time_get();
12432      }
12433
12434    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
12435
12436    bdresize = bd;
12437    return 1;
12438 }
12439
12440 static int
12441 _e_border_resize_end(E_Border *bd)
12442 {
12443    if (grabbed)
12444      {
12445         e_grabinput_release(bd->win, bd->win);
12446         grabbed = 0;
12447      }
12448    if (bd->client.netwm.sync.alarm)
12449      {
12450         E_Border_Pending_Move_Resize *pnd;
12451
12452         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12453         bd->client.netwm.sync.alarm = 0;
12454         /* resize to last geometry if sync alarm for it was not yet handled */
12455         if (bd->pending_move_resize)
12456           {
12457              bd->changed = 1;
12458              bd->changes.pos = 1;
12459              bd->changes.size = 1;
12460              _e_border_client_move_resize_send(bd);
12461           }
12462
12463         EINA_LIST_FREE(bd->pending_move_resize, pnd)
12464           E_FREE(pnd);
12465      }
12466
12467    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
12468
12469    bdresize = NULL;
12470
12471    /* If this border was maximized, we need to unset Maximized state or
12472     * on restart, E still thinks it's maximized */
12473    if (bd->maximized != E_MAXIMIZE_NONE)
12474      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
12475                                   bd->maximized & E_MAXIMIZE_NONE);
12476    return 1;
12477 }
12478
12479 static void
12480 _e_border_resize_update(E_Border *bd)
12481 {
12482    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
12483 }
12484
12485 static int
12486 _e_border_move_begin(E_Border *bd)
12487 {
12488    int ret;
12489    if (!bd->lock_user_stacking)
12490      {
12491         if (e_config->border_raise_on_mouse_action)
12492           e_border_raise(bd);
12493      }
12494    if ((bd->fullscreen) || (bd->lock_user_location))
12495      return 0;
12496
12497    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12498      ret = e_grabinput_get(bd->win, 0, bd->win);
12499    else
12500      ret = e_grabinput_get(bd->win, 0, 0);
12501
12502    if (grabbed && !ret)
12503      {
12504         grabbed = 0;
12505         return 0;
12506      }
12507 #if 0
12508    if (bd->client.netwm.sync.request)
12509      {
12510         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12511         bd->client.netwm.sync.serial = 0;
12512         bd->client.netwm.sync.wait = 0;
12513         bd->client.netwm.sync.time = ecore_loop_time_get();
12514      }
12515 #endif
12516    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
12517
12518    bdmove = bd;
12519    return 1;
12520 }
12521
12522 static int
12523 _e_border_move_end(E_Border *bd)
12524 {
12525    if (grabbed)
12526      {
12527         e_grabinput_release(bd->win, bd->win);
12528         grabbed = 0;
12529      }
12530 #if 0
12531    if (bd->client.netwm.sync.alarm)
12532      {
12533         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12534         bd->client.netwm.sync.alarm = 0;
12535      }
12536 #endif
12537    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
12538
12539    bdmove = NULL;
12540    return 1;
12541 }
12542
12543 static void
12544 _e_border_move_update(E_Border *bd)
12545 {
12546    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
12547 }
12548
12549 static Eina_Bool
12550 _e_border_cb_ping_poller(void *data)
12551 {
12552    E_Border *bd;
12553
12554    bd = data;
12555    if (bd->ping_ok)
12556      {
12557         if (bd->hung)
12558           {
12559              bd->hung = 0;
12560              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
12561              if (bd->kill_timer)
12562                {
12563                   ecore_timer_del(bd->kill_timer);
12564                   bd->kill_timer = NULL;
12565                }
12566           }
12567      }
12568    else
12569      {
12570         /* if time between last ping and now is greater
12571          * than half the ping interval... */
12572         if ((ecore_loop_time_get() - bd->ping) >
12573             ((e_config->ping_clients_interval *
12574               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
12575           {
12576              if (!bd->hung)
12577                {
12578                   bd->hung = 1;
12579                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
12580                   /* FIXME: if below dialog is up - hide it now */
12581                }
12582              if (bd->delete_requested)
12583                {
12584                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
12585                   e_border_act_kill_begin(bd);
12586                }
12587           }
12588      }
12589    bd->ping_poller = NULL;
12590    e_border_ping(bd);
12591    return ECORE_CALLBACK_CANCEL;
12592 }
12593
12594 static Eina_Bool
12595 _e_border_cb_kill_timer(void *data)
12596 {
12597    E_Border *bd;
12598
12599    bd = data;
12600 // dont wait until it's hung -
12601 //   if (bd->hung)
12602 //     {
12603         if (bd->client.netwm.pid > 1)
12604           kill(bd->client.netwm.pid, SIGKILL);
12605 //     }
12606    bd->kill_timer = NULL;
12607    return ECORE_CALLBACK_CANCEL;
12608 }
12609
12610 static void
12611 _e_border_pointer_resize_begin(E_Border *bd)
12612 {
12613    switch (bd->resize_mode)
12614      {
12615       case RESIZE_TL:
12616         e_pointer_type_push(bd->pointer, bd, "resize_tl");
12617         break;
12618
12619       case RESIZE_T:
12620         e_pointer_type_push(bd->pointer, bd, "resize_t");
12621         break;
12622
12623       case RESIZE_TR:
12624         e_pointer_type_push(bd->pointer, bd, "resize_tr");
12625         break;
12626
12627       case RESIZE_R:
12628         e_pointer_type_push(bd->pointer, bd, "resize_r");
12629         break;
12630
12631       case RESIZE_BR:
12632         e_pointer_type_push(bd->pointer, bd, "resize_br");
12633         break;
12634
12635       case RESIZE_B:
12636         e_pointer_type_push(bd->pointer, bd, "resize_b");
12637         break;
12638
12639       case RESIZE_BL:
12640         e_pointer_type_push(bd->pointer, bd, "resize_bl");
12641         break;
12642
12643       case RESIZE_L:
12644         e_pointer_type_push(bd->pointer, bd, "resize_l");
12645         break;
12646      }
12647 }
12648
12649 static void
12650 _e_border_pointer_resize_end(E_Border *bd)
12651 {
12652    switch (bd->resize_mode)
12653      {
12654       case RESIZE_TL:
12655         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
12656         break;
12657
12658       case RESIZE_T:
12659         e_pointer_type_pop(bd->pointer, bd, "resize_t");
12660         break;
12661
12662       case RESIZE_TR:
12663         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
12664         break;
12665
12666       case RESIZE_R:
12667         e_pointer_type_pop(bd->pointer, bd, "resize_r");
12668         break;
12669
12670       case RESIZE_BR:
12671         e_pointer_type_pop(bd->pointer, bd, "resize_br");
12672         break;
12673
12674       case RESIZE_B:
12675         e_pointer_type_pop(bd->pointer, bd, "resize_b");
12676         break;
12677
12678       case RESIZE_BL:
12679         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
12680         break;
12681
12682       case RESIZE_L:
12683         e_pointer_type_pop(bd->pointer, bd, "resize_l");
12684         break;
12685      }
12686 }
12687
12688 static void
12689 _e_border_pointer_move_begin(E_Border *bd)
12690 {
12691    e_pointer_type_push(bd->pointer, bd, "move");
12692 }
12693
12694 static void
12695 _e_border_pointer_move_end(E_Border *bd)
12696 {
12697    e_pointer_type_pop(bd->pointer, bd, "move");
12698 }
12699
12700 static Eina_List *_e_border_hooks = NULL;
12701 static int _e_border_hooks_delete = 0;
12702 static int _e_border_hooks_walking = 0;
12703
12704 static void
12705 _e_border_hooks_clean(void)
12706 {
12707    Eina_List *l, *ln;
12708    E_Border_Hook *bh;
12709
12710    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
12711      {
12712         if (bh->delete_me)
12713           {
12714              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
12715              free(bh);
12716           }
12717      }
12718 }
12719
12720 static void
12721 _e_border_hook_call(E_Border_Hook_Point hookpoint,
12722                     void               *bd)
12723 {
12724    Eina_List *l;
12725    E_Border_Hook *bh;
12726
12727    _e_border_hooks_walking++;
12728    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
12729      {
12730         if (bh->delete_me) continue;
12731         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
12732      }
12733    _e_border_hooks_walking--;
12734    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
12735      _e_border_hooks_clean();
12736 }
12737
12738 EAPI E_Border_Hook *
12739 e_border_hook_add(E_Border_Hook_Point               hookpoint,
12740                   void                              (*func)(void *data,
12741                                               void *bd),
12742                   void                             *data)
12743 {
12744    E_Border_Hook *bh;
12745
12746    bh = E_NEW(E_Border_Hook, 1);
12747    if (!bh) return NULL;
12748    bh->hookpoint = hookpoint;
12749    bh->func = func;
12750    bh->data = data;
12751    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
12752    return bh;
12753 }
12754
12755 EAPI void
12756 e_border_hook_del(E_Border_Hook *bh)
12757 {
12758    bh->delete_me = 1;
12759    if (_e_border_hooks_walking == 0)
12760      {
12761         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
12762         free(bh);
12763      }
12764    else
12765      _e_border_hooks_delete++;
12766 }
12767
12768 EAPI void
12769 e_border_focus_track_freeze(void)
12770 {
12771    focus_track_frozen++;
12772 }
12773
12774 EAPI void
12775 e_border_focus_track_thaw(void)
12776 {
12777    focus_track_frozen--;
12778 }
12779
12780 EAPI E_Border *
12781 e_border_under_pointer_get(E_Desk   *desk,
12782                            E_Border *exclude)
12783 {
12784    E_Border *bd = NULL, *cbd;
12785    Eina_List *l;
12786    int x, y;
12787
12788    /* We need to ensure that we can get the container window for the
12789     * zone of either the given desk or the desk of the excluded
12790     * window, so return if neither is given */
12791    if (desk)
12792      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
12793    else if (exclude)
12794      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
12795    else
12796      return NULL;
12797
12798    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
12799      {
12800         if (!cbd) continue;
12801         /* If a border was specified which should be excluded from the list
12802          * (because it will be closed shortly for example), skip */
12803         if ((exclude) && (cbd == exclude)) continue;
12804         if ((desk) && (cbd->desk != desk)) continue;
12805         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
12806           continue;
12807         /* If the layer is higher, the position of the window is higher
12808          * (always on top vs always below) */
12809         if (!bd || (cbd->layer > bd->layer))
12810           {
12811              bd = cbd;
12812              break;
12813           }
12814      }
12815    return bd;
12816 }
12817
12818 static Eina_Bool
12819 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
12820 {
12821    if (warp_to)
12822      {
12823         int x, y;
12824         double spd;
12825
12826         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
12827         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
12828             (y - warp_y) > 5 || (y - warp_y) < -5)
12829           {
12830              /* User moved the mouse, so stop warping */
12831              warp_to = 0;
12832              goto cleanup;
12833           }
12834
12835         /* We just use the same warp speed as configured
12836          * for the windowlist */
12837         spd = e_config->winlist_warp_speed;
12838         x = warp_x;
12839         y = warp_y;
12840         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12841         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12842         if (warp_x == x && warp_y == y)
12843           {
12844              warp_x = warp_to_x;
12845              warp_y = warp_to_y;
12846              warp_to = 0;
12847              goto cleanup;
12848           }
12849         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12850         return ECORE_CALLBACK_RENEW;
12851      }
12852  cleanup:
12853    ecore_timer_del(warp_timer);
12854    warp_timer = NULL;
12855    return ECORE_CALLBACK_CANCEL;
12856 }
12857
12858 EAPI int
12859 e_border_pointer_warp_to_center(E_Border *bd)
12860 {
12861    int x, y;
12862
12863    /* Do not slide pointer when disabled (probably breaks focus
12864     * on sloppy/mouse focus but requested by users). */
12865    if (!e_config->pointer_slide) return 0;
12866    /* Only warp the pointer if it is not already in the area of
12867     * the given border */
12868    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12869    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12870        (y >= bd->y) && (y <= (bd->y + bd->h)))
12871      return 0;
12872
12873    warp_to_x = bd->x + (bd->w / 2);
12874    if (warp_to_x < (bd->zone->x + 1))
12875      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12876    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12877      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12878
12879    warp_to_y = bd->y + (bd->h / 2);
12880    if (warp_to_y < (bd->zone->y + 1))
12881      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12882    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12883      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12884
12885    warp_to = 1;
12886    warp_to_win = bd->zone->container->win;
12887    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12888    if (!warp_timer)
12889      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12890    return 1;
12891 }
12892
12893 EAPI void
12894 e_border_comp_hidden_set(E_Border *bd,
12895                          Eina_Bool hidden)
12896 {
12897    E_Border *tmp;
12898    Eina_List *l;
12899
12900    E_OBJECT_CHECK(bd);
12901    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12902
12903    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12904      {
12905        if (hidden)
12906          ecore_x_window_hide(tmp->win);
12907        else
12908          ecore_x_window_show(tmp->win);
12909      }
12910
12911    if (bd->comp_hidden == hidden) return;
12912
12913    bd->comp_hidden = hidden;
12914
12915    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12916      {
12917         ecore_x_composite_window_events_disable(bd->win);
12918         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12919      }
12920    else
12921      {
12922         _e_border_shape_input_rectangle_set(bd);
12923         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12924      }
12925 }
12926
12927 EAPI void
12928 e_border_tmp_input_hidden_push(E_Border *bd)
12929 {
12930    E_Border *tmp;
12931    Eina_List *l;
12932
12933    E_OBJECT_CHECK(bd);
12934    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12935
12936    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12937      e_border_tmp_input_hidden_push(tmp);
12938
12939    bd->tmp_input_hidden++;
12940    if (bd->tmp_input_hidden != 1) return;
12941
12942    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12943      {
12944         ecore_x_composite_window_events_disable(bd->win);
12945         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12946      }
12947    else
12948      {
12949         _e_border_shape_input_rectangle_set(bd);
12950         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12951      }
12952 }
12953
12954 EAPI void
12955 e_border_tmp_input_hidden_pop(E_Border *bd)
12956 {
12957    E_Border *tmp;
12958    Eina_List *l;
12959
12960    E_OBJECT_CHECK(bd);
12961    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12962
12963    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12964      e_border_tmp_input_hidden_pop(tmp);
12965
12966    bd->tmp_input_hidden--;
12967    if (bd->tmp_input_hidden != 0) return;
12968
12969    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12970      {
12971         ecore_x_composite_window_events_disable(bd->win);
12972         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12973      }
12974    else
12975      {
12976         _e_border_shape_input_rectangle_set(bd);
12977         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12978      }
12979 }
12980
12981 EAPI void
12982 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
12983 {
12984    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
12985        ((bd->parent) &&
12986         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
12987          ((bd->parent->focused) &&
12988           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
12989        (just_do_it))
12990      {
12991         if (bd->iconic)
12992           {
12993              if (e_config->clientlist_warp_to_iconified_desktop == 1)
12994                e_desk_show(bd->desk);
12995              
12996              if (!bd->lock_user_iconify)
12997                e_border_uniconify(bd);
12998           }
12999         if ((!bd->iconic) && (!bd->sticky))
13000           e_desk_show(bd->desk);
13001         if (!bd->lock_user_stacking) e_border_raise(bd);
13002         if (!bd->lock_focus_out)
13003           {
13004              /* XXX ooffice does send this request for
13005               config dialogs when the main window gets focus.
13006               causing the pointer to jump back and forth.  */
13007              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
13008                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
13009                ecore_x_pointer_warp(bd->zone->container->win,
13010                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
13011              e_border_focus_set(bd, 1, 1);
13012           }
13013      }
13014 }
13015
13016 #ifdef _F_DEICONIFY_APPROVE_
13017 static void
13018 _e_border_window_pending_destroy_event_free(void *data __UNUSED__,
13019                                             void *ev)
13020 {
13021    Ecore_X_Event_Window_Destroy *e;
13022
13023    e = ev;
13024    E_FREE(e);
13025 }
13026
13027 static void
13028 _e_border_window_pending_hide_event_free(void *data __UNUSED__,
13029                                          void *ev)
13030 {
13031    Ecore_X_Event_Window_Hide *e;
13032
13033    e = ev;
13034    E_FREE(e);
13035 }
13036
13037 static void
13038 _e_border_window_pending_hide_event_send(E_Border *bd)
13039 {
13040    Ecore_X_Event_Window_Hide *e;
13041
13042    if (!bd) return;
13043
13044    e = E_NEW(Ecore_X_Event_Window_Hide, 1);
13045    if (e)
13046      {
13047         e->win = bd->client.e.state.pending_event.hide.win;
13048         e->event_win = bd->client.e.state.pending_event.hide.event_win;
13049         e->time = ecore_x_current_time_get();
13050         e->send_event = bd->client.e.state.pending_event.hide.send_event;
13051
13052         ecore_event_add(ECORE_X_EVENT_WINDOW_HIDE, e,
13053                         _e_border_window_pending_hide_event_free, NULL);
13054
13055         ELB(ELBT_BD, "Send pended HIDE event", e->win);
13056      }
13057 }
13058
13059 static void
13060 _e_border_window_pending_destroy_event_send(E_Border *bd)
13061 {
13062    Ecore_X_Event_Window_Destroy *e;
13063
13064    if (!bd) return;
13065
13066    e = E_NEW(Ecore_X_Event_Window_Destroy, 1);
13067    if (e)
13068      {
13069         e->win = bd->client.e.state.pending_event.destroy.win;
13070         e->event_win = bd->client.e.state.pending_event.destroy.event_win;
13071         e->time = ecore_x_current_time_get();
13072
13073         ecore_event_add(ECORE_X_EVENT_WINDOW_DESTROY, e,
13074                         _e_border_window_pending_destroy_event_free, NULL);
13075
13076         ELB(ELBT_BD, "Send pended DESTROY event", e->win);
13077      }
13078 }
13079
13080 static void
13081 _e_border_msg_handler(void       *data,
13082                       const char *name,
13083                       const char *info,
13084                       int         val,
13085                       E_Object   *obj,
13086                       void       *msgdata)
13087 {
13088    E_Manager *man = (E_Manager *)obj;
13089    E_Manager_Comp_Source *src = (E_Manager_Comp_Source *)msgdata;
13090
13091    // handle only comp.manager msg
13092    if (strncmp(name, "comp.manager", sizeof("comp.manager"))) return;
13093
13094    if (!strncmp(info, "visibility.src", sizeof("visibility.src")))
13095      {
13096         Ecore_X_Window win;
13097         E_Border *bd;
13098         Eina_Bool visible;
13099
13100         win = e_manager_comp_src_window_get(man, src);
13101         bd = e_border_find_by_window(win);
13102
13103         if (!bd) return;
13104         if (!bd->client.e.state.deiconify_approve.pending_bd) return;
13105
13106         visible = e_manager_comp_src_visible_get(man, src);
13107         if (visible)
13108           {
13109              E_Border *pending_bd = bd->client.e.state.deiconify_approve.pending_bd;
13110              if (!pending_bd->client.e.state.pending_event.pending)
13111                {
13112                   bd->client.e.state.deiconify_approve.pending_bd = NULL;
13113                   return;
13114                }
13115
13116              pending_bd->client.e.state.pending_event.done = 1;
13117              pending_bd->client.e.state.pending_event.hold_bd = NULL;
13118
13119              if (pending_bd->client.e.state.pending_event.hide.pending)
13120                {
13121                   _e_border_window_pending_hide_event_send(pending_bd);
13122
13123                   // clear hide event data
13124                   pending_bd->client.e.state.pending_event.hide.pending = 0;
13125                   pending_bd->client.e.state.pending_event.hide.win = 0;
13126                   pending_bd->client.e.state.pending_event.hide.event_win = 0;
13127                   pending_bd->client.e.state.pending_event.hide.send_event = 0;
13128                }
13129
13130              if (pending_bd->client.e.state.pending_event.destroy.pending)
13131                {
13132                   _e_border_window_pending_destroy_event_send(pending_bd);
13133
13134                   // clear destroy event data
13135                   pending_bd->client.e.state.pending_event.destroy.pending = 0;
13136                   pending_bd->client.e.state.pending_event.destroy.win = 0;
13137                   pending_bd->client.e.state.pending_event.destroy.event_win = 0;
13138                }
13139
13140              bd->client.e.state.deiconify_approve.pending_bd = NULL;
13141              ELBF(ELBT_ROT, 0, bd->client.win, "RESET pending_bd:%x", bd->client.e.state.deiconify_approve.pending_bd);
13142           }
13143      }
13144 }
13145 #endif
13146 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/