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