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