There is un-expected case that border's geometry is not updated after performing...
[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_start(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_pre_resize(E_Border *bd, int *x, int *y, int *w, int *h);
170 static Eina_Bool _e_border_rotation_check(E_Border *bd);
171 static Eina_Bool _e_border_rotation_zone_check(E_Zone *zone);
172 static Eina_Bool _e_border_rotation_border_check(E_Border *bd, int ang);
173 static Eina_Bool _e_border_rotation_zone_vkbd_check(E_Zone *zone);
174 static Eina_Bool _e_border_rotation_vkbd_transient_for_check(E_Border *bd);
175 static Eina_Bool _e_border_rotation_transient_for_check(E_Border *bd, int ang);
176 static Eina_Bool _e_border_cb_window_configure(void *data,
177                                                int   ev_type,
178                                                void *ev);
179 static Eina_Bool _e_border_vkbd_show_prepare_timeout(void *data);
180 static Eina_Bool _e_border_vkbd_hide_prepare_timeout(void *data);
181 static void      _e_border_vkbd_show(E_Border *bd);
182 static void      _e_border_vkbd_hide(E_Border *bd);
183 #endif
184 static void      _e_border_move_resize_internal(E_Border *bd,
185                                                 int       x,
186                                                 int       y,
187                                                 int       w,
188                                                 int       h,
189                                                 Eina_Bool without_border,
190                                                 Eina_Bool move);
191
192 static void      _e_border_eval(E_Border *bd);
193 static void      _e_border_eval0(E_Border *bd);
194 static void      _e_border_container_layout_hook(E_Container *con);
195
196 static void      _e_border_moveinfo_gather(E_Border   *bd,
197                                            const char *source);
198 static void      _e_border_resize_handle(E_Border *bd);
199
200 static Eina_Bool _e_border_shade_animator(void *data);
201
202 static void      _e_border_event_border_add_free(void *data,
203                                                  void *ev);
204 static void      _e_border_event_border_remove_free(void *data,
205                                                     void *ev);
206 static void      _e_border_event_border_zone_set_free(void *data,
207                                                       void *ev);
208 static void      _e_border_event_border_desk_set_free(void *data,
209                                                       void *ev);
210 static void      _e_border_event_border_stack_free(void *data,
211                                                    void *ev);
212 static void      _e_border_event_border_icon_change_free(void *data,
213                                                          void *ev);
214 static void      _e_border_event_border_urgent_change_free(void *data,
215                                                            void *ev);
216 static void      _e_border_event_border_focus_in_free(void *data,
217                                                       void *ev);
218 static void      _e_border_event_border_focus_out_free(void *data,
219                                                        void *ev);
220 static void      _e_border_event_border_resize_free(void *data,
221                                                     void *ev);
222 static void      _e_border_event_border_move_free(void *data,
223                                                   void *ev);
224 static void      _e_border_event_border_show_free(void *data,
225                                                   void *ev);
226 static void      _e_border_event_border_hide_free(void *data,
227                                                   void *ev);
228 static void      _e_border_event_border_iconify_free(void *data,
229                                                      void *ev);
230 static void      _e_border_event_border_uniconify_free(void *data,
231                                                        void *ev);
232 static void      _e_border_event_border_stick_free(void *data,
233                                                    void *ev);
234 static void      _e_border_event_border_unstick_free(void *data,
235                                                      void *ev);
236 static void      _e_border_event_border_property_free(void *data,
237                                                       void *ev);
238 static void      _e_border_event_border_fullscreen_free(void *data,
239                                                         void *ev);
240 static void      _e_border_event_border_unfullscreen_free(void *data,
241                                                           void *ev);
242 #ifdef _F_ZONE_WINDOW_ROTATION_
243 static void      _e_border_event_border_rotation_change_begin_free(void *data,
244                                                                    void *ev);
245 static void      _e_border_event_border_rotation_change_cancel_free(void *data,
246                                                                     void *ev);
247 static void      _e_border_event_border_rotation_change_end_free(void *data,
248                                                                  void *ev);
249 static void      _e_border_event_border_rotation_change_begin_send(E_Border *bd);
250 #endif
251
252 static void      _e_border_zone_update(E_Border *bd);
253
254 static int       _e_border_resize_begin(E_Border *bd);
255 static int       _e_border_resize_end(E_Border *bd);
256 static void      _e_border_resize_update(E_Border *bd);
257
258 static int       _e_border_move_begin(E_Border *bd);
259 static int       _e_border_move_end(E_Border *bd);
260 static void      _e_border_move_update(E_Border *bd);
261
262 static Eina_Bool _e_border_cb_ping_poller(void *data);
263 static Eina_Bool _e_border_cb_kill_timer(void *data);
264
265 static void      _e_border_pointer_resize_begin(E_Border *bd);
266 static void      _e_border_pointer_resize_end(E_Border *bd);
267 static void      _e_border_pointer_move_begin(E_Border *bd);
268 static void      _e_border_pointer_move_end(E_Border *bd);
269
270 static void      _e_border_hook_call(E_Border_Hook_Point hookpoint,
271                                      void               *bd);
272
273 static void _e_border_client_move_resize_send(E_Border *bd);
274
275 static void _e_border_frame_replace(E_Border *bd,
276             Eina_Bool argb);
277
278 static void _e_border_shape_input_rectangle_set(E_Border* bd);
279 static void _e_border_show(E_Border *bd);
280 static void _e_border_hide(E_Border *bd);
281
282
283 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
284 static void _e_border_latest_stacked_focus (E_Border* bd);
285 static void _e_border_check_stack (E_Border *bd);
286 static void _e_border_focus_top_stack_set (E_Border* bd);
287 #endif
288 #if _F_BORDER_CLIP_TO_ZONE_
289 static void      _e_border_shape_input_clip_to_zone(E_Border *bd);
290 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
291 /* local subsystem globals */
292 static Eina_List *handlers = NULL;
293 static Eina_List *borders = NULL;
294 static Eina_Hash *borders_hash = NULL;
295 static E_Border *focused = NULL;
296 static E_Border *focusing = NULL;
297 static Eina_List *focus_next = NULL;
298 static Ecore_X_Time focus_time = 0;
299
300 static E_Border *bdresize = NULL;
301 static E_Border *bdmove = NULL;
302 static E_Drag *drag_border = NULL;
303
304 static int grabbed = 0;
305
306 static Eina_List *focus_stack = NULL;
307 static Eina_List *raise_stack = NULL;
308
309 static Ecore_X_Randr_Screen_Size screen_size = { -1, -1 };
310 static int screen_size_index = -1;
311
312 static int focus_track_frozen = 0;
313
314 static int warp_to = 0;
315 static int warp_to_x = 0;
316 static int warp_to_y = 0;
317 static int warp_x = 0;
318 static int warp_y = 0;
319 static Ecore_X_Window warp_to_win;
320 static Ecore_Timer *warp_timer = NULL;
321
322 #ifdef _F_ZONE_WINDOW_ROTATION_
323 typedef struct _E_Border_Rotation      E_Border_Rotation;
324 typedef struct _E_Border_Rotation_Info E_Border_Rotation_Info;
325
326 struct _E_Border_Rotation
327 {
328    Eina_List     *list;
329
330    Eina_Bool      wait_prepare_done;
331    Ecore_Timer   *prepare_timer;
332    Ecore_Timer   *done_timer;
333
334    Ecore_X_Window vkbd_ctrl_win;
335    E_Border      *vkbd;
336    E_Border      *vkbd_prediction;
337
338    /* vkbd show/hide preprare */
339    Eina_Bool      vkbd_show_prepare_done;
340    Ecore_Timer   *vkbd_show_prepare_timer;
341    Ecore_Timer   *vkbd_show_timer;
342
343    Eina_Bool      vkbd_hide_prepare_done;
344    Ecore_Timer   *vkbd_hide_prepare_timer;
345    Ecore_Timer   *vkbd_hide_timer;
346
347    Eina_Bool      fetch;
348    Eina_List     *msgs;
349 };
350
351 struct _E_Border_Rotation_Info
352 {
353    int            x, y, w, h;
354    int            ang;
355    E_Border      *bd;
356    Eina_Bool      win_resize;
357 };
358
359 static E_Border_Rotation rot =
360 {
361    NULL,
362    EINA_FALSE,
363    NULL,
364    NULL,
365    0,
366    NULL,
367    NULL,
368    EINA_FALSE,
369    NULL,
370    NULL,
371    EINA_FALSE,
372    NULL,
373    NULL,
374    EINA_FALSE,
375    NULL
376 };
377 #endif
378
379 EAPI int E_EVENT_BORDER_ADD = 0;
380 EAPI int E_EVENT_BORDER_REMOVE = 0;
381 EAPI int E_EVENT_BORDER_ZONE_SET = 0;
382 EAPI int E_EVENT_BORDER_DESK_SET = 0;
383 EAPI int E_EVENT_BORDER_RESIZE = 0;
384 EAPI int E_EVENT_BORDER_MOVE = 0;
385 EAPI int E_EVENT_BORDER_SHOW = 0;
386 EAPI int E_EVENT_BORDER_HIDE = 0;
387 EAPI int E_EVENT_BORDER_ICONIFY = 0;
388 EAPI int E_EVENT_BORDER_UNICONIFY = 0;
389 EAPI int E_EVENT_BORDER_STICK = 0;
390 EAPI int E_EVENT_BORDER_UNSTICK = 0;
391 EAPI int E_EVENT_BORDER_STACK = 0;
392 EAPI int E_EVENT_BORDER_ICON_CHANGE = 0;
393 EAPI int E_EVENT_BORDER_URGENT_CHANGE = 0;
394 EAPI int E_EVENT_BORDER_FOCUS_IN = 0;
395 EAPI int E_EVENT_BORDER_FOCUS_OUT = 0;
396 EAPI int E_EVENT_BORDER_PROPERTY = 0;
397 EAPI int E_EVENT_BORDER_FULLSCREEN = 0;
398 EAPI int E_EVENT_BORDER_UNFULLSCREEN = 0;
399 #ifdef _F_ZONE_WINDOW_ROTATION_
400 EAPI int E_EVENT_BORDER_ROTATION = 0; /* deprecated */
401 EAPI int E_EVENT_BORDER_ROTATION_CHANGE_BEGIN = 0;
402 EAPI int E_EVENT_BORDER_ROTATION_CHANGE_CANCEL = 0;
403 EAPI int E_EVENT_BORDER_ROTATION_CHANGE_END = 0;
404 #endif
405
406 #define GRAV_SET(bd, grav)                                \
407   ecore_x_window_gravity_set(bd->bg_win, grav);           \
408   ecore_x_window_gravity_set(bd->client.shell_win, grav); \
409   ecore_x_window_gravity_set(bd->client.win, grav);
410
411 static Eina_List *
412 _e_border_sub_borders_new(E_Border *bd)
413 {
414    Eina_List *list = NULL, *l;
415    E_Border *child;
416    E_Border_List *bl;
417
418    EINA_LIST_FOREACH(bd->transients, l, child)
419      {
420         if (!eina_list_data_find(list, child))
421           list = eina_list_append(list, child);
422      }
423    bl = e_container_border_list_first(bd->zone->container);
424    while ((child = e_container_border_list_next(bl)))
425      {
426         if (e_object_is_del(E_OBJECT(child))) continue;
427         if (child == bd) continue;
428 /*
429         if ((bd->client.icccm.client_leader) &&
430             (child->client.icccm.client_leader ==
431                 bd->client.icccm.client_leader))
432           {
433              printf("bd %s in group with %s\n",
434                     e_border_name_get(child),
435                     e_border_name_get(bd));
436              if (!eina_list_data_find(list, child))
437                list = eina_list_append(list, child);
438           }
439  */
440      }
441    e_container_border_list_free(bl);
442    return list;
443 }
444
445 /* externally accessible functions */
446 EINTERN int
447 e_border_init(void)
448 {
449    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, _e_border_cb_window_show_request, NULL));
450    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _e_border_cb_window_destroy, NULL));
451    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, _e_border_cb_window_hide, NULL));
452    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_REPARENT, _e_border_cb_window_reparent, NULL));
453    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, _e_border_cb_window_configure_request, NULL));
454    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, _e_border_cb_window_resize_request, NULL));
455    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_GRAVITY, _e_border_cb_window_gravity, NULL));
456    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, _e_border_cb_window_stack_request, NULL));
457    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _e_border_cb_window_property, NULL));
458    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_COLORMAP, _e_border_cb_window_colormap, NULL));
459    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHAPE, _e_border_cb_window_shape, NULL));
460    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, _e_border_cb_window_focus_in, NULL));
461    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _e_border_cb_window_focus_out, NULL));
462    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _e_border_cb_client_message, NULL));
463    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, _e_border_cb_window_state_request, NULL));
464    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, _e_border_cb_window_move_resize_request, NULL));
465    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_DESKTOP_CHANGE, _e_border_cb_desktop_change, NULL));
466    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_SYNC_ALARM, _e_border_cb_sync_alarm, NULL));
467 #ifdef _F_ZONE_WINDOW_ROTATION_
468    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, _e_border_cb_window_configure, NULL));
469 #endif
470
471    ecore_x_passive_grab_replay_func_set(_e_border_cb_grab_replay, NULL);
472
473    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_POINTER_WARP, _e_border_cb_pointer_warp, NULL));
474    handlers = eina_list_append(handlers, ecore_event_handler_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE, _e_border_cb_efreet_cache_update, NULL));
475    handlers = eina_list_append(handlers, ecore_event_handler_add(EFREET_EVENT_ICON_CACHE_UPDATE, _e_border_cb_efreet_cache_update, NULL));
476    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_CONFIG_ICON_THEME, _e_border_cb_config_icon_theme, NULL));
477 #ifdef _F_USE_DESK_WINDOW_PROFILE_
478    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_DESK_WINDOW_PROFILE_CHANGE, _e_border_cb_desk_window_profile_change, NULL));
479 #endif
480 #ifdef _F_ZONE_WINDOW_ROTATION_
481    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, _e_border_cb_zone_rotation_change_begin, NULL));
482 #endif
483
484    if (!borders_hash) borders_hash = eina_hash_string_superfast_new(NULL);
485
486    E_EVENT_BORDER_ADD = ecore_event_type_new();
487    E_EVENT_BORDER_REMOVE = ecore_event_type_new();
488    E_EVENT_BORDER_DESK_SET = ecore_event_type_new();
489    E_EVENT_BORDER_ZONE_SET = ecore_event_type_new();
490    E_EVENT_BORDER_RESIZE = ecore_event_type_new();
491    E_EVENT_BORDER_MOVE = ecore_event_type_new();
492    E_EVENT_BORDER_SHOW = ecore_event_type_new();
493    E_EVENT_BORDER_HIDE = ecore_event_type_new();
494    E_EVENT_BORDER_ICONIFY = ecore_event_type_new();
495    E_EVENT_BORDER_UNICONIFY = ecore_event_type_new();
496    E_EVENT_BORDER_STICK = ecore_event_type_new();
497    E_EVENT_BORDER_UNSTICK = ecore_event_type_new();
498    E_EVENT_BORDER_STACK = ecore_event_type_new();
499    E_EVENT_BORDER_ICON_CHANGE = ecore_event_type_new();
500    E_EVENT_BORDER_URGENT_CHANGE = ecore_event_type_new();
501    E_EVENT_BORDER_FOCUS_IN = ecore_event_type_new();
502    E_EVENT_BORDER_FOCUS_OUT = ecore_event_type_new();
503    E_EVENT_BORDER_PROPERTY = ecore_event_type_new();
504    E_EVENT_BORDER_FULLSCREEN = ecore_event_type_new();
505    E_EVENT_BORDER_UNFULLSCREEN = ecore_event_type_new();
506 #ifdef _F_ZONE_WINDOW_ROTATION_
507    E_EVENT_BORDER_ROTATION = ecore_event_type_new(); /* deprecated */
508    E_EVENT_BORDER_ROTATION_CHANGE_BEGIN = ecore_event_type_new();
509    E_EVENT_BORDER_ROTATION_CHANGE_CANCEL = ecore_event_type_new();
510    E_EVENT_BORDER_ROTATION_CHANGE_END = ecore_event_type_new();
511 #endif
512
513 //   e_init_undone();
514
515    return 1;
516 }
517
518 EINTERN int
519 e_border_shutdown(void)
520 {
521    E_FREE_LIST(handlers, ecore_event_handler_del);
522
523    if (borders_hash) eina_hash_free(borders_hash);
524    borders_hash = NULL;
525    e_int_border_menu_hooks_clear();
526
527    return 1;
528 }
529
530 EAPI E_Border *
531 e_border_new(E_Container   *con,
532              Ecore_X_Window win,
533              int            first_map,
534              int            internal)
535 {
536    E_Border *bd, *bd2;
537    Ecore_X_Window_Attributes *att;
538    unsigned int managed, desk[2];
539    int deskx, desky;
540
541    bd = E_OBJECT_ALLOC(E_Border, E_BORDER_TYPE, _e_border_free);
542    if (!bd) return NULL;
543    ecore_x_window_shadow_tree_flush();
544    e_object_del_func_set(E_OBJECT(bd), E_OBJECT_CLEANUP_FUNC(_e_border_del));
545
546    bd->w = 1;
547    bd->h = 1;
548    /* FIXME: ewww - round trip */
549    bd->client.argb = ecore_x_window_argb_get(win);
550    if (bd->client.argb)
551      bd->win = ecore_x_window_manager_argb_new(con->win, 0, 0, bd->w, bd->h);
552    else
553      {
554         bd->win = ecore_x_window_override_new(con->win, 0, 0, bd->w, bd->h);
555         ecore_x_window_shape_events_select(bd->win, 1);
556      }
557    e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
558    e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
559    e_focus_setup(bd);
560    bd->bg_ecore_evas = e_canvas_new(bd->win,
561                                     0, 0, bd->w, bd->h, 1, 0,
562                                     &(bd->bg_win));
563    ecore_evas_ignore_events_set(bd->bg_ecore_evas, EINA_TRUE);
564    e_canvas_add(bd->bg_ecore_evas);
565    bd->event_win = ecore_x_window_input_new(bd->win, 0, 0, bd->w, bd->h);
566    bd->bg_evas = ecore_evas_get(bd->bg_ecore_evas);
567    ecore_x_window_shape_events_select(bd->bg_win, 1);
568    ecore_evas_name_class_set(bd->bg_ecore_evas, "E", "Frame_Window");
569    ecore_evas_title_set(bd->bg_ecore_evas, "Enlightenment Frame");
570    if (bd->client.argb)
571      bd->client.shell_win = ecore_x_window_manager_argb_new(bd->win, 0, 0, 1, 1);
572    else
573      bd->client.shell_win = ecore_x_window_override_new(bd->win, 0, 0, 1, 1);
574    ecore_x_window_container_manage(bd->client.shell_win);
575    if (!internal) ecore_x_window_client_manage(win);
576    /* FIXME: Round trip. XCB */
577    /* fetch needed to avoid grabbing the server as window may vanish */
578    att = &bd->client.initial_attributes;
579    if ((!ecore_x_window_attributes_get(win, att)) || (att->input_only))
580      {
581         //      printf("##- ATTR FETCH FAILED/INPUT ONLY FOR 0x%x - ABORT MANAGE\n", win);
582           e_canvas_del(bd->bg_ecore_evas);
583           ecore_evas_free(bd->bg_ecore_evas);
584           ecore_x_window_free(bd->client.shell_win);
585           e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
586           e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
587           ecore_x_window_free(bd->win);
588           free(bd);
589           return NULL;
590      }
591
592    /* printf("##- ON MAP CLIENT 0x%x SIZE %ix%i %i:%i\n",
593     *     bd->client.win, bd->client.w, bd->client.h, att->x, att->y); */
594
595    /* FIXME: if first_map is 1 then we should ignore the first hide event
596     * or ensure the window is already hidden and events flushed before we
597     * create a border for it */
598    if (first_map)
599      {
600         // printf("##- FIRST MAP\n");
601           bd->x = att->x;
602           bd->y = att->y;
603           bd->changes.pos = 1;
604           bd->re_manage = 1;
605           // needed to be 1 for internal windw and on restart.
606           // bd->ignore_first_unmap = 2;
607      }
608
609    bd->client.win = win;
610    bd->zone = e_zone_current_get(con);
611
612    _e_border_hook_call(E_BORDER_HOOK_NEW_BORDER, bd);
613
614    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN, _e_border_cb_mouse_in, bd));
615    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT, _e_border_cb_mouse_out, bd));
616    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_cb_mouse_down, bd));
617    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, _e_border_cb_mouse_up, bd));
618    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, _e_border_cb_mouse_move, bd));
619    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL, _e_border_cb_mouse_wheel, bd));
620
621    bd->client.icccm.title = NULL;
622    bd->client.icccm.name = NULL;
623    bd->client.icccm.class = NULL;
624    bd->client.icccm.icon_name = NULL;
625    bd->client.icccm.machine = NULL;
626    bd->client.icccm.min_w = 1;
627    bd->client.icccm.min_h = 1;
628    bd->client.icccm.max_w = 32767;
629    bd->client.icccm.max_h = 32767;
630    bd->client.icccm.base_w = 0;
631    bd->client.icccm.base_h = 0;
632    bd->client.icccm.step_w = -1;
633    bd->client.icccm.step_h = -1;
634    bd->client.icccm.min_aspect = 0.0;
635    bd->client.icccm.max_aspect = 0.0;
636    bd->client.icccm.accepts_focus = 1;
637
638    bd->client.netwm.pid = 0;
639    bd->client.netwm.name = NULL;
640    bd->client.netwm.icon_name = NULL;
641    bd->client.netwm.desktop = 0;
642    bd->client.netwm.state.modal = 0;
643    bd->client.netwm.state.sticky = 0;
644    bd->client.netwm.state.shaded = 0;
645    bd->client.netwm.state.hidden = 0;
646    bd->client.netwm.state.maximized_v = 0;
647    bd->client.netwm.state.maximized_h = 0;
648    bd->client.netwm.state.skip_taskbar = 0;
649    bd->client.netwm.state.skip_pager = 0;
650    bd->client.netwm.state.fullscreen = 0;
651    bd->client.netwm.state.stacking = E_STACKING_NONE;
652    bd->client.netwm.action.move = 0;
653    bd->client.netwm.action.resize = 0;
654    bd->client.netwm.action.minimize = 0;
655    bd->client.netwm.action.shade = 0;
656    bd->client.netwm.action.stick = 0;
657    bd->client.netwm.action.maximized_h = 0;
658    bd->client.netwm.action.maximized_v = 0;
659    bd->client.netwm.action.fullscreen = 0;
660    bd->client.netwm.action.change_desktop = 0;
661    bd->client.netwm.action.close = 0;
662    bd->client.netwm.type = ECORE_X_WINDOW_TYPE_UNKNOWN;
663
664    {
665       int at_num = 0, i;
666       Ecore_X_Atom *atoms;
667
668       atoms = ecore_x_window_prop_list(bd->client.win, &at_num);
669       bd->client.icccm.fetch.command = 1;
670       if (atoms)
671         {
672            Eina_Bool video_parent = EINA_FALSE;
673            Eina_Bool video_position = EINA_FALSE;
674
675            /* icccm */
676             for (i = 0; i < at_num; i++)
677               {
678                  if (atoms[i] == ECORE_X_ATOM_WM_NAME)
679                    bd->client.icccm.fetch.title = 1;
680                  else if (atoms[i] == ECORE_X_ATOM_WM_CLASS)
681                    bd->client.icccm.fetch.name_class = 1;
682                  else if (atoms[i] == ECORE_X_ATOM_WM_ICON_NAME)
683                    bd->client.icccm.fetch.icon_name = 1;
684                  else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_MACHINE)
685                    bd->client.icccm.fetch.machine = 1;
686                  else if (atoms[i] == ECORE_X_ATOM_WM_HINTS)
687                    bd->client.icccm.fetch.hints = 1;
688                  else if (atoms[i] == ECORE_X_ATOM_WM_NORMAL_HINTS)
689                    bd->client.icccm.fetch.size_pos_hints = 1;
690                  else if (atoms[i] == ECORE_X_ATOM_WM_PROTOCOLS)
691                    bd->client.icccm.fetch.protocol = 1;
692                  else if (atoms[i] == ECORE_X_ATOM_MOTIF_WM_HINTS)
693                    bd->client.mwm.fetch.hints = 1;
694                  else if (atoms[i] == ECORE_X_ATOM_WM_TRANSIENT_FOR)
695                    {
696                       bd->client.icccm.fetch.transient_for = 1;
697                       bd->client.netwm.fetch.type = 1;
698                    }
699                  else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_LEADER)
700                    bd->client.icccm.fetch.client_leader = 1;
701                  else if (atoms[i] == ECORE_X_ATOM_WM_WINDOW_ROLE)
702                    bd->client.icccm.fetch.window_role = 1;
703                  else if (atoms[i] == ECORE_X_ATOM_WM_STATE)
704                    bd->client.icccm.fetch.state = 1;
705               }
706             /* netwm, loop again, netwm will ignore some icccm, so we
707              * have to be sure that netwm is checked after */
708             for (i = 0; i < at_num; i++)
709               {
710                  if (atoms[i] == ECORE_X_ATOM_NET_WM_NAME)
711                    {
712      /* Ignore icccm */
713                        bd->client.icccm.fetch.title = 0;
714                        bd->client.netwm.fetch.name = 1;
715                    }
716                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON_NAME)
717                    {
718      /* Ignore icccm */
719                        bd->client.icccm.fetch.icon_name = 0;
720                        bd->client.netwm.fetch.icon_name = 1;
721                    }
722                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON)
723                    {
724                       bd->client.netwm.fetch.icon = 1;
725                    }
726                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_USER_TIME)
727                    {
728                       bd->client.netwm.fetch.user_time = 1;
729                    }
730                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT)
731                    {
732                       DBG("ECORE_X_ATOM_NET_WM_STRUT");
733                       bd->client.netwm.fetch.strut = 1;
734                    }
735                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
736                    {
737                       DBG("ECORE_X_ATOM_NET_WM_STRUT_PARTIAL");
738                       bd->client.netwm.fetch.strut = 1;
739                    }
740                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_TYPE)
741                    {
742      /* Ignore mwm
743         bd->client.mwm.fetch.hints = 0;
744       */
745                         bd->client.netwm.fetch.type = 1;
746                    }
747                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STATE)
748                    {
749                       bd->client.netwm.fetch.state = 1;
750                    }
751               }
752             /* other misc atoms */
753             for (i = 0; i < at_num; i++)
754               {
755      /* loop to check for own atoms */
756                   if (atoms[i] == E_ATOM_WINDOW_STATE)
757                     {
758                        bd->client.e.fetch.state = 1;
759                     }
760      /* loop to check for qtopia atoms */
761                   if (atoms[i] == ATM__QTOPIA_SOFT_MENU)
762                     bd->client.qtopia.fetch.soft_menu = 1;
763                   else if (atoms[i] == ATM__QTOPIA_SOFT_MENUS)
764                     bd->client.qtopia.fetch.soft_menus = 1;
765      /* loop to check for vkbd atoms */
766                   else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
767                     bd->client.vkbd.fetch.state = 1;
768                   else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
769                     bd->client.vkbd.fetch.vkbd = 1;
770      /* loop to check for illume atoms */
771                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
772                     bd->client.illume.conformant.fetch.conformant = 1;
773                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
774                     bd->client.illume.quickpanel.fetch.state = 1;
775                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
776                     bd->client.illume.quickpanel.fetch.quickpanel = 1;
777                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
778                     bd->client.illume.quickpanel.fetch.priority.major = 1;
779                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
780                     bd->client.illume.quickpanel.fetch.priority.minor = 1;
781                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
782                     bd->client.illume.quickpanel.fetch.zone = 1;
783                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
784                     bd->client.illume.drag.fetch.locked = 1;
785                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG)
786                     bd->client.illume.drag.fetch.drag = 1;
787                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
788                     bd->client.illume.win_state.fetch.state = 1;
789                   else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_PARENT)
790                     video_parent = EINA_TRUE;
791                   else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_POSITION)
792                     video_position = EINA_TRUE;
793 #ifdef _F_USE_DESK_WINDOW_PROFILE_
794      /* loop to check for window profile list atom */
795                   else if (atoms[i] == ECORE_X_ATOM_E_PROFILE_LIST)
796                     bd->client.e.fetch.profile_list = 1;
797 #endif
798 #ifdef _F_ZONE_WINDOW_ROTATION_
799                   /* loop to check for wm rotation */
800                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED)
801                     {
802                        if (e_config->wm_win_rotation)
803                          bd->client.e.fetch.rot.support = 1;
804                     }
805                   else if ((atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) ||
806                            (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) ||
807                            (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) ||
808                            (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY))
809                     {
810                        if (e_config->wm_win_rotation)
811                          bd->client.e.fetch.rot.geom_hint = 1;
812                     }
813                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED)
814                     {
815                        if (e_config->wm_win_rotation)
816                          bd->client.e.fetch.rot.app_set = 1;
817                     }
818                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION)
819                     {
820                        if (e_config->wm_win_rotation)
821                          bd->client.e.fetch.rot.preferred_rot = 1;
822                     }
823                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)
824                     {
825                        if (e_config->wm_win_rotation)
826                          bd->client.e.fetch.rot.available_rots = 1;
827                     }
828 #endif
829 #ifdef _F_DEICONIFY_APPROVE_
830                   else if (atoms[i] == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
831                     {
832                        bd->client.e.state.deiconify_approve.support = 1;
833                     }
834 #endif
835               }
836             if (video_position && video_parent)
837               {
838                  bd->client.e.state.video = 1;
839                  bd->client.e.fetch.video_parent = 1;
840                  bd->client.e.fetch.video_position = 1;
841                  ecore_x_window_lower(bd->win);
842                  ecore_x_composite_window_events_disable(bd->win);
843                  ecore_x_window_ignore_set(bd->win, EINA_TRUE);
844                  fprintf(stderr, "We found a video window \\o/ %x\n", win);
845               }
846             free(atoms);
847         }
848    }
849    bd->client.border.changed = 1;
850
851    bd->client.w = att->w;
852    bd->client.h = att->h;
853
854    bd->w = bd->client.w;
855    bd->h = bd->client.h;
856
857    bd->resize_mode = RESIZE_NONE;
858    bd->layer = 100;
859    bd->saved.layer = bd->layer;
860    bd->changes.icon = 1;
861    bd->changes.size = 1;
862    bd->changes.shape = 1;
863    bd->changes.shape_input = 1;
864
865    bd->offer_resistance = 1;
866
867    /* just to friggin make java happy - we're DELAYING the reparent until
868     * eval time...
869     */
870 /*   ecore_x_window_reparent(win, bd->client.shell_win, 0, 0); */
871    bd->need_reparent = 1;
872
873    ecore_x_window_border_width_set(win, 0);
874    ecore_x_window_show(bd->event_win);
875    ecore_x_window_show(bd->client.shell_win);
876    bd->shape = e_container_shape_add(con);
877
878    bd->take_focus = 1;
879    bd->new_client = 1;
880    bd->changed = 1;
881 #ifdef _F_ZONE_WINDOW_ROTATION_
882    bd->client.e.state.rot.preferred_rot = -1;
883    bd->client.e.state.rot.type = E_BORDER_ROTATION_TYPE_NORMAL;
884 #endif
885
886 //   bd->zone = e_zone_current_get(con);
887    bd->desk = e_desk_current_get(bd->zone);
888    e_container_border_add(bd);
889    borders = eina_list_append(borders, bd);
890    bd2 = eina_hash_find(borders_hash, e_util_winid_str_get(bd->client.win));
891    if (bd2)
892      {
893 #ifdef E_LOGGING
894         WRN("EEEEK! 2 borders with same client window id in them! very bad!\n"
895             "optimisations failing due to bizarre client behavior. will\n"
896             "work around.\n"
897             "bd=%p, bd->references=%i, bd->deleted=%i, bd->client.win=%x",
898                bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted,
899                bd2->client.win);
900
901         ELBF(ELBT_BD, 0, bd->client.win,
902              "ERR! 2 borders with same client win id in them! bd:%p ref:%i deleted:%i",
903              bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted);
904 #else
905         printf("EEEEK! 2 borders with same client window id in them! very bad!\n");
906         printf("optimisations failing due to bizarre client behavior. will\n");
907         printf("work around.\n");
908         printf("bd=%p, bd->references=%i, bd->deleted=%i, bd->client.win=%x\n",
909                bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted,
910                bd2->client.win);
911
912         ELBF(ELBT_BD, 0, bd->client.win,
913              "ERR! 2 borders with same client win id in them! bd:%p ref:%i deleted:%i",
914              bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted);
915 #endif
916
917 #ifdef _F_ZONE_WINDOW_ROTATION_
918         if ((rot.vkbd) && (rot.vkbd == bd2))
919           {
920              ELB(ELBT_BD, "UNSET VKBD", rot.vkbd->client.win);
921              ELBF(ELBT_BD, 1, rot.vkbd->client.win, "VKBD HIDE PREPARE_DONE:%d",
922                   rot.vkbd_hide_prepare_done);
923
924              if (rot.vkbd_hide_prepare_timer)
925                {
926                   ecore_timer_del(rot.vkbd_hide_prepare_timer);
927                   rot.vkbd_hide_prepare_timer = NULL;
928
929                   e_object_unref(E_OBJECT(bd2));
930                }
931
932              _e_border_vkbd_hide(rot.vkbd);
933
934              if (rot.vkbd_ctrl_win)
935                {
936                   ELB(ELBT_BD, "SET KBD_OFF", 0);
937                   ecore_x_e_virtual_keyboard_state_set
938                      (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
939                }
940              rot.vkbd_hide_prepare_done = EINA_FALSE;
941
942              if (rot.vkbd_hide_timer)
943                ecore_timer_del(rot.vkbd_hide_timer);
944              rot.vkbd_hide_timer = NULL;
945
946              rot.vkbd_show_prepare_done = EINA_FALSE;
947              if (rot.vkbd_show_prepare_timer)
948                ecore_timer_del(rot.vkbd_show_prepare_timer);
949              rot.vkbd_show_prepare_timer = NULL;
950              if (rot.vkbd_show_timer)
951                ecore_timer_del(rot.vkbd_show_timer);
952              rot.vkbd_show_timer = NULL;
953
954              rot.vkbd = NULL;
955           }
956 #endif
957         eina_hash_del(borders_hash, e_util_winid_str_get(bd->client.win), bd2);
958         eina_hash_del(borders_hash, e_util_winid_str_get(bd2->bg_win), bd2);
959         eina_hash_del(borders_hash, e_util_winid_str_get(bd2->win), bd2);
960      }
961    eina_hash_add(borders_hash, e_util_winid_str_get(bd->client.win), bd);
962    eina_hash_add(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
963    eina_hash_add(borders_hash, e_util_winid_str_get(bd->win), bd);
964    managed = 1;
965    ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &managed, 1);
966    ecore_x_window_prop_card32_set(win, E_ATOM_CONTAINER, &bd->zone->container->num, 1);
967    ecore_x_window_prop_card32_set(win, E_ATOM_ZONE, &bd->zone->num, 1);
968      {
969         unsigned int zgeom[4];
970         
971         zgeom[0] = bd->zone->x;
972         zgeom[1] = bd->zone->y;
973         zgeom[2] = bd->zone->w;
974         zgeom[3] = bd->zone->h;
975         ecore_x_window_prop_card32_set(win, E_ATOM_ZONE_GEOMETRY, zgeom, 4);
976      }
977    e_desk_xy_get(bd->desk, &deskx, &desky);
978    desk[0] = deskx;
979    desk[1] = desky;
980    ecore_x_window_prop_card32_set(win, E_ATOM_DESK, desk, 2);
981 #ifdef _F_USE_DESK_WINDOW_PROFILE_
982    if (strcmp(bd->desk->window_profile,
983               e_config->desktop_default_window_profile) != 0)
984      {
985         ecore_x_e_window_profile_set(bd->client.win,
986                                      bd->desk->window_profile);
987      }
988 #endif
989
990    focus_stack = eina_list_append(focus_stack, bd);
991
992    bd->pointer = e_pointer_window_new(bd->win, 0);
993    return bd;
994 }
995
996 EAPI void
997 e_border_res_change_geometry_save(E_Border *bd)
998 {
999    E_OBJECT_CHECK(bd);
1000    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1001
1002    if (bd->pre_res_change.valid) return;
1003    bd->pre_res_change.valid = 1;
1004    bd->pre_res_change.x = bd->x;
1005    bd->pre_res_change.y = bd->y;
1006    bd->pre_res_change.w = bd->w;
1007    bd->pre_res_change.h = bd->h;
1008    bd->pre_res_change.saved.x = bd->saved.x;
1009    bd->pre_res_change.saved.y = bd->saved.y;
1010    bd->pre_res_change.saved.w = bd->saved.w;
1011    bd->pre_res_change.saved.h = bd->saved.h;
1012 }
1013
1014 EAPI void
1015 e_border_res_change_geometry_restore(E_Border *bd)
1016 {
1017    struct
1018    {
1019       unsigned char valid : 1;
1020       int           x, y, w, h;
1021       struct
1022       {
1023          int x, y, w, h;
1024       } saved;
1025    } pre_res_change;
1026
1027    E_OBJECT_CHECK(bd);
1028    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1029    if (!bd->pre_res_change.valid) return;
1030    if (bd->new_client) return;
1031
1032    ecore_x_window_shadow_tree_flush();
1033    memcpy(&pre_res_change, &bd->pre_res_change, sizeof(pre_res_change));
1034
1035    if (bd->fullscreen)
1036      {
1037         e_border_unfullscreen(bd);
1038         e_border_fullscreen(bd, e_config->fullscreen_policy);
1039      }
1040    else if (bd->maximized != E_MAXIMIZE_NONE)
1041      {
1042         E_Maximize max;
1043
1044         max = bd->maximized;
1045         e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
1046         e_border_maximize(bd, max);
1047      }
1048    else
1049      {
1050         int x, y, w, h, zx, zy, zw, zh;
1051
1052         bd->saved.x = bd->pre_res_change.saved.x;
1053         bd->saved.y = bd->pre_res_change.saved.y;
1054         bd->saved.w = bd->pre_res_change.saved.w;
1055         bd->saved.h = bd->pre_res_change.saved.h;
1056
1057         e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
1058
1059         if (bd->saved.w > zw)
1060           bd->saved.w = zw;
1061         if ((bd->saved.x + bd->saved.w) > (zx + zw))
1062           bd->saved.x = zx + zw - bd->saved.w;
1063
1064         if (bd->saved.h > zh)
1065           bd->saved.h = zh;
1066         if ((bd->saved.y + bd->saved.h) > (zy + zh))
1067           bd->saved.y = zy + zh - bd->saved.h;
1068
1069         x = bd->pre_res_change.x;
1070         y = bd->pre_res_change.y;
1071         w = bd->pre_res_change.w;
1072         h = bd->pre_res_change.h;
1073         if (w > zw)
1074           w = zw;
1075         if (h > zh)
1076           h = zh;
1077         if ((x + w) > (zx + zw))
1078           x = zx + zw - w;
1079         if ((y + h) > (zy + zh))
1080           y = zy + zh - h;
1081         e_border_move_resize(bd, x, y, w, h);
1082      }
1083    memcpy(&bd->pre_res_change, &pre_res_change, sizeof(pre_res_change));
1084 }
1085
1086 EAPI void
1087 e_border_zone_set(E_Border *bd,
1088                   E_Zone   *zone)
1089 {
1090    E_Event_Border_Zone_Set *ev;
1091
1092    E_OBJECT_CHECK(bd);
1093    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1094    E_OBJECT_CHECK(zone);
1095    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1096    if (!zone) return;
1097    if (bd->zone == zone) return;
1098
1099    /* if the window does not lie in the new zone, move it so that it does */
1100    if (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))
1101      {
1102         int x, y;
1103         /* first guess -- get offset from old zone, and apply to new zone */
1104         x = zone->x + (bd->x - bd->zone->x);
1105         y = zone->y + (bd->y - bd->zone->y);
1106
1107         /* keep window from hanging off bottom and left */
1108         if (x + bd->w > zone->x + zone->w) x += (zone->x + zone->w) - (x + bd->w);
1109         if (y + bd->h > zone->y + zone->h) y += (zone->y + zone->h) - (y + bd->h);
1110
1111         /* make sure to and left are on screen (if the window is larger than the zone, it will hang off the bottom / right) */
1112         if (x < zone->x) x = zone->x;
1113         if (y < zone->y) y = zone->y;
1114
1115         if (!E_INTERSECTS(x, y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))
1116           {
1117              /* still not in zone at all, so just move it to closest edge */
1118               if (x < zone->x) x = zone->x;
1119               if (x >= zone->x + zone->w) x = zone->x + zone->w - bd->w;
1120               if (y < zone->y) y = zone->y;
1121               if (y >= zone->y + zone->h) y = zone->y + zone->h - bd->h;
1122           }
1123         e_border_move(bd, x, y);
1124      }
1125
1126    bd->zone = zone;
1127
1128    if (bd->desk->zone != bd->zone)
1129      e_border_desk_set(bd, e_desk_current_get(bd->zone));
1130
1131    ev = E_NEW(E_Event_Border_Zone_Set, 1);
1132    ev->border = bd;
1133    e_object_ref(E_OBJECT(bd));
1134 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_zone_set_event");
1135    ev->zone = zone;
1136    e_object_ref(E_OBJECT(zone));
1137
1138    ecore_event_add(E_EVENT_BORDER_ZONE_SET, ev, _e_border_event_border_zone_set_free, NULL);
1139
1140    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_ZONE, &bd->zone->num, 1);
1141    // XXXXXXXXXXXXXXXXXXXXXXXXX
1142    // XXX ZZZZZZZZZZZZZZZZZZZzz
1143    // need to adjust this if zone pos/size changes
1144      {
1145         unsigned int zgeom[4];
1146         
1147         zgeom[0] = bd->zone->x;
1148         zgeom[1] = bd->zone->y;
1149         zgeom[2] = bd->zone->w;
1150         zgeom[3] = bd->zone->h;
1151         ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_ZONE_GEOMETRY, zgeom, 4);
1152      }
1153    e_remember_update(bd);
1154 }
1155
1156 EAPI void
1157 e_border_desk_set(E_Border *bd,
1158                   E_Desk   *desk)
1159 {
1160    E_Event_Border_Desk_Set *ev;
1161    E_Desk *old_desk;
1162
1163    E_OBJECT_CHECK(bd);
1164    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1165    E_OBJECT_CHECK(desk);
1166    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1167    if (bd->desk == desk) return;
1168    ecore_x_window_shadow_tree_flush();
1169    if (bd->fullscreen)
1170      {
1171         bd->desk->fullscreen_borders--;
1172         desk->fullscreen_borders++;
1173      }
1174    old_desk = bd->desk;
1175    bd->desk = desk;
1176    e_border_zone_set(bd, desk->zone);
1177
1178    _e_border_hook_call(E_BORDER_HOOK_SET_DESK, bd);
1179    e_hints_window_desktop_set(bd);
1180
1181    ev = E_NEW(E_Event_Border_Desk_Set, 1);
1182    ev->border = bd;
1183    e_object_ref(E_OBJECT(bd));
1184 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_desk_set_event");
1185    ev->desk = old_desk;
1186    e_object_ref(E_OBJECT(old_desk));
1187    ecore_event_add(E_EVENT_BORDER_DESK_SET, ev, _e_border_event_border_desk_set_free, NULL);
1188
1189    if (bd->ignore_first_unmap != 1)
1190      {
1191         if ((bd->desk->visible) || (bd->sticky))
1192           e_border_show(bd);
1193         else
1194           e_border_hide(bd, 1);
1195      }
1196
1197    if (e_config->transient.desktop)
1198      {
1199         Eina_List *l;
1200         E_Border *child;
1201         Eina_List *list = _e_border_sub_borders_new(bd);
1202
1203         EINA_LIST_FOREACH(list, l, child)
1204           {
1205              e_border_desk_set(child, bd->desk);
1206           }
1207         eina_list_free(list);
1208      }
1209    e_remember_update(bd);
1210 }
1211
1212 #ifdef _F_ZONE_WINDOW_ROTATION_
1213 static Eina_Bool
1214 _e_border_vkbd_state_check(E_Border *bd,
1215                            Eina_Bool show)
1216 {
1217    Eina_Bool res = EINA_TRUE;
1218    if (!e_config->wm_win_rotation) return EINA_FALSE;
1219    if ((rot.vkbd) && (rot.vkbd == bd))
1220      {
1221         if (show)
1222           {
1223              if ((rot.vkbd_hide_prepare_done) ||
1224                  (rot.vkbd_hide_prepare_timer))
1225                res = EINA_FALSE;
1226           }
1227         else
1228           {
1229              if ((rot.vkbd_show_prepare_done) ||
1230                  (rot.vkbd_show_prepare_timer))
1231                res = EINA_FALSE;
1232           }
1233      }
1234    return res;
1235 }
1236
1237 static Eina_Bool
1238 _e_border_vkbd_show_timeout(void *data)
1239 {
1240    E_Border *bd = data;
1241    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1242    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1243      {
1244         if (_e_border_vkbd_state_check(bd, EINA_TRUE))
1245           {
1246              if (rot.vkbd_ctrl_win)
1247                {
1248                   ELB(ELBT_BD, "SET KBD_ON", 0);
1249                   ecore_x_e_virtual_keyboard_state_set
1250                     (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1251                }
1252           }
1253      }
1254
1255    rot.vkbd_show_prepare_done = EINA_FALSE;
1256
1257    if (rot.vkbd_show_prepare_timer)
1258      ecore_timer_del(rot.vkbd_show_prepare_timer);
1259    rot.vkbd_show_prepare_timer = NULL;
1260
1261    if (rot.vkbd_show_timer)
1262      ecore_timer_del(rot.vkbd_show_timer);
1263    rot.vkbd_show_timer = NULL;
1264
1265    return ECORE_CALLBACK_CANCEL;
1266 }
1267
1268 static Eina_Bool
1269 _e_border_vkbd_hide_timeout(void *data)
1270 {
1271    E_Border *bd = data;
1272    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1273    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1274      {
1275         if (_e_border_vkbd_state_check(bd, EINA_FALSE))
1276           {
1277              if (rot.vkbd_ctrl_win)
1278                {
1279                   ELB(ELBT_BD, "SET KBD_OFF", 0);
1280                   ecore_x_e_virtual_keyboard_state_set
1281                     (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1282                }
1283           }
1284         e_object_unref(E_OBJECT(bd));
1285      }
1286
1287    rot.vkbd_hide_prepare_done = EINA_FALSE;
1288
1289    if (rot.vkbd_hide_prepare_timer)
1290      ecore_timer_del(rot.vkbd_hide_prepare_timer);
1291    rot.vkbd_hide_prepare_timer = NULL;
1292
1293    if (rot.vkbd_hide_timer)
1294      ecore_timer_del(rot.vkbd_hide_timer);
1295    rot.vkbd_hide_timer = NULL;
1296
1297    return ECORE_CALLBACK_CANCEL;
1298 }
1299
1300 static void
1301 _e_border_vkbd_show(E_Border *bd)
1302 {
1303    if (!e_config->wm_win_rotation) return;
1304    rot.vkbd_show_prepare_done = EINA_TRUE;
1305    if (rot.vkbd_show_prepare_timer)
1306      ecore_timer_del(rot.vkbd_show_prepare_timer);
1307    rot.vkbd_show_prepare_timer = NULL;
1308    if (rot.vkbd_show_timer)
1309      ecore_timer_del(rot.vkbd_show_timer);
1310    rot.vkbd_show_timer = NULL;
1311    if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
1312      {
1313         e_border_show(bd);
1314         rot.vkbd_show_timer = ecore_timer_add(0.1f, _e_border_vkbd_show_timeout, bd);
1315      }
1316 }
1317
1318 static void
1319 _e_border_vkbd_hide(E_Border *bd)
1320 {
1321    if (!e_config->wm_win_rotation) return;
1322    rot.vkbd_hide_prepare_done = EINA_TRUE;
1323    if (rot.vkbd_hide_prepare_timer)
1324      ecore_timer_del(rot.vkbd_hide_prepare_timer);
1325    rot.vkbd_hide_prepare_timer = NULL;
1326    if (rot.vkbd_hide_timer)
1327      ecore_timer_del(rot.vkbd_hide_timer);
1328    rot.vkbd_hide_timer = NULL;
1329    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1330      {
1331         ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
1332         e_border_hide(bd, 0);
1333         if (!e_object_is_del(E_OBJECT(bd)))
1334           {
1335              ELB(ELBT_BD, "DEL VKBD", bd->client.win);
1336              e_object_del(E_OBJECT(bd));
1337           }
1338         rot.vkbd_hide_timer = ecore_timer_add(0.03f, _e_border_vkbd_hide_timeout, bd);
1339      }
1340 }
1341
1342 static Eina_Bool
1343 _e_border_vkbd_show_prepare_timeout(void *data)
1344 {
1345    E_Border *bd = data;
1346    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1347    if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
1348      {
1349         ELB(ELBT_BD, "TIMEOUT KBD_SHOW_PREPARE", bd->client.win);
1350         _e_border_vkbd_show(bd);
1351      }
1352    return ECORE_CALLBACK_CANCEL;
1353 }
1354
1355 static Eina_Bool
1356 _e_border_vkbd_hide_prepare_timeout(void *data)
1357 {
1358    E_Border *bd = data;
1359    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1360    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1361      {
1362         ELB(ELBT_BD, "TIMEOUT KBD_HIDE_PREPARE", bd->client.win);
1363         _e_border_vkbd_hide(bd);
1364      }
1365    return ECORE_CALLBACK_CANCEL;
1366 }
1367 #endif
1368
1369 EAPI void
1370 e_border_show(E_Border *bd)
1371 {
1372    E_Event_Border_Show *ev;
1373    unsigned int visible;
1374
1375    E_OBJECT_CHECK(bd);
1376    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1377    if (bd->visible) return;
1378 #ifdef _F_ZONE_WINDOW_ROTATION_
1379    if ((e_config->wm_win_rotation) &&
1380        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
1381        (bd == rot.vkbd) &&
1382        (!rot.vkbd_show_prepare_done))
1383      {
1384         ELB(ELBT_BD, "SEND KBD_ON_PREPARE", bd->client.win);
1385         ecore_x_e_virtual_keyboard_on_prepare_request_send(rot.vkbd_ctrl_win);
1386         if (rot.vkbd_show_prepare_timer)
1387           ecore_timer_del(rot.vkbd_show_prepare_timer);
1388         rot.vkbd_show_prepare_timer = ecore_timer_add(1.5f,
1389                                                       _e_border_vkbd_show_prepare_timeout,
1390                                                       bd);
1391         return;
1392      }
1393    ELB(ELBT_BD, "SHOW", bd->client.win);
1394 #endif
1395    ecore_x_window_shadow_tree_flush();
1396    e_container_shape_show(bd->shape);
1397    if (!bd->need_reparent)
1398      ecore_x_window_show(bd->client.win);
1399    e_hints_window_visible_set(bd);
1400    bd->hidden = 0;
1401    bd->visible = 1;
1402    bd->changes.visible = 1;
1403
1404    visible = 1;
1405    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
1406    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
1407
1408    ev = E_NEW(E_Event_Border_Show, 1);
1409    ev->border = bd;
1410    e_object_ref(E_OBJECT(bd));
1411 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_show_event");
1412    ecore_event_add(E_EVENT_BORDER_SHOW, ev, _e_border_event_border_show_free, NULL);
1413
1414 #ifdef _F_ZONE_WINDOW_ROTATION_
1415    if ((e_config->wm_win_rotation) &&
1416        ((bd->client.e.state.rot.support) ||
1417         (bd->client.e.state.rot.app_set)))
1418      {
1419         ELB(ELBT_ROT, "CHECK", bd->client.win);
1420         Eina_Bool _rot = _e_border_rotation_check(bd);
1421         /* check whether rotation is available for sub borders such as prediction and magnifier */
1422         if (_rot)
1423           {
1424              Eina_List *ll;
1425              E_Border *_child;
1426              Eina_List *_list = _e_border_sub_borders_new(bd);
1427              EINA_LIST_FOREACH(_list, ll, _child)
1428                {
1429                   if ((_child->client.e.state.rot.support) ||
1430                       (_child->client.e.state.rot.app_set))
1431                     _e_border_rotation_check(_child);
1432                }
1433              eina_list_free(_list);
1434           }
1435      }
1436 #endif
1437 }
1438
1439 EAPI void
1440 e_border_hide(E_Border *bd,
1441               int       manage)
1442 {
1443    unsigned int visible;
1444
1445    E_OBJECT_CHECK(bd);
1446    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1447
1448 #ifdef _F_ZONE_WINDOW_ROTATION_
1449    if ((e_config->wm_win_rotation) &&
1450        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
1451        (bd == rot.vkbd) &&
1452        (!rot.vkbd_hide_prepare_done) &&
1453        (!bd->iconic))
1454      {
1455         Eina_Bool need_prepare = EINA_TRUE;
1456         E_Border *child = NULL;
1457         if (bd->parent)
1458           {
1459              if (e_object_is_del(E_OBJECT(bd->parent)))
1460                need_prepare = EINA_FALSE;
1461              else
1462                {
1463                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
1464                   if (bd->parent->modal == bd)
1465                     {
1466                        ecore_x_event_mask_unset(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
1467                        ecore_x_event_mask_set(bd->parent->client.win, bd->parent->saved.event_mask);
1468                        bd->parent->lock_close = 0;
1469                        bd->parent->saved.event_mask = 0;
1470                        bd->parent->modal = NULL;
1471                     }
1472                   bd->parent = NULL;
1473                }
1474           }
1475         else
1476           need_prepare = EINA_FALSE;
1477
1478         EINA_LIST_FREE(bd->transients, child)
1479           {
1480              child->parent = NULL;
1481           }
1482
1483         ELBF(ELBT_BD, 0, bd->client.win, "SEND KBD_OFF_PREPARE:%d", need_prepare);
1484
1485         if (need_prepare)
1486           {
1487              e_object_ref(E_OBJECT(bd));
1488              ecore_x_e_virtual_keyboard_off_prepare_request_send(rot.vkbd_ctrl_win);
1489              if (rot.vkbd_hide_prepare_timer)
1490                ecore_timer_del(rot.vkbd_hide_prepare_timer);
1491              rot.vkbd_hide_prepare_timer = ecore_timer_add(1.5f,
1492                                                            _e_border_vkbd_hide_prepare_timeout,
1493                                                            bd);
1494              return;
1495           }
1496         else
1497           {
1498              e_object_ref(E_OBJECT(bd));
1499
1500              /* In order to clear conformant area properly, WM should send keyboard off prepare request event */
1501              ecore_x_e_virtual_keyboard_off_prepare_request_send(rot.vkbd_ctrl_win);
1502
1503              /* cleanup code from _e_border_vkbd_hide() */
1504              rot.vkbd_hide_prepare_done = EINA_TRUE;
1505              if (rot.vkbd_hide_prepare_timer)
1506                ecore_timer_del(rot.vkbd_hide_prepare_timer);
1507              rot.vkbd_hide_prepare_timer = NULL;
1508              if (rot.vkbd_hide_timer)
1509                ecore_timer_del(rot.vkbd_hide_timer);
1510              rot.vkbd_hide_timer = ecore_timer_add(0.03f, _e_border_vkbd_hide_timeout, bd);
1511           }
1512      }
1513    ELBF(ELBT_BD, 0, bd->client.win, "HIDE visible:%d", bd->visible);
1514 #endif
1515    if (!bd->visible) goto send_event;
1516    ecore_x_window_shadow_tree_flush();
1517    if (bd->moving)
1518      _e_border_move_end(bd);
1519    if (bd->resize_mode != RESIZE_NONE)
1520      {
1521         _e_border_pointer_resize_end(bd);
1522         bd->resize_mode = RESIZE_NONE;
1523         _e_border_resize_end(bd);
1524      }
1525
1526    e_container_shape_hide(bd->shape);
1527    if (!bd->iconic) e_hints_window_hidden_set(bd);
1528
1529    bd->visible = 0;
1530    bd->changes.visible = 1;
1531
1532    if (!bd->need_reparent)
1533      {
1534         if ((bd->focused) ||
1535             (e_grabinput_last_focus_win_get() == bd->client.win))
1536           {
1537              e_border_focus_set(bd, 0, 1);
1538              if (manage != 2)
1539                {
1540                   E_Border *pbd;
1541                   E_Container *con;
1542                   E_Zone *zone;
1543                   E_Desk *desk;
1544
1545                   con = e_container_current_get(e_manager_current_get());
1546                   zone = e_zone_current_get(con);
1547                   desk = e_desk_current_get(zone);
1548
1549                   if ((bd->parent) &&
1550                       (bd->parent->desk == desk) && (bd->parent->modal == bd))
1551                     e_border_focus_set(bd->parent, 1, 1);
1552                   else if (e_config->focus_revert_on_hide_or_close)
1553                     {
1554                        /* When using pointer focus, the border under the
1555                         * pointer (if any) gets focused, in sloppy/click
1556                         * focus the last focused window on the current
1557                         * desk gets focus */
1558                        if (e_config->focus_policy == E_FOCUS_MOUSE)
1559                          {
1560                             pbd = e_border_under_pointer_get(desk, bd);
1561                             if (pbd)
1562                               e_border_focus_set(pbd, 1, 1);
1563                          }
1564 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
1565                        else if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) &&
1566                                 (e_config->focus_policy == E_FOCUS_CLICK))
1567                          _e_border_latest_stacked_focus(bd);
1568 #endif
1569
1570                        else
1571                          e_desk_last_focused_focus(desk);
1572                     }
1573                }
1574           }
1575         switch (manage)
1576           {
1577            case 2: break;
1578            case 3:
1579              bd->hidden = 1;
1580            case 1:
1581              /* Make sure that this border isn't deleted */
1582              bd->await_hide_event++;
1583            default:
1584              if (!e_manager_comp_evas_get(bd->zone->container->manager))
1585                ecore_x_window_hide(bd->client.win);
1586           }
1587      }
1588
1589    visible = 0;
1590    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
1591    if (!manage)
1592      ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
1593
1594    bd->post_show = 0;
1595
1596 send_event:
1597    if (!stopping)
1598      {
1599 #ifdef _F_ZONE_WINDOW_ROTATION_
1600         _e_border_rotation_list_remove(bd);
1601 #endif
1602
1603         E_Event_Border_Hide *ev;
1604
1605         ev = E_NEW(E_Event_Border_Hide, 1);
1606         ev->border = bd;
1607         e_object_ref(E_OBJECT(bd));
1608 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_hide_event");
1609         ecore_event_add(E_EVENT_BORDER_HIDE, ev, _e_border_event_border_hide_free, NULL);
1610      }
1611 }
1612
1613 static void
1614 _pri_adj(int pid, int set, int adj, Eina_Bool use_adj, Eina_Bool adj_children, Eina_Bool do_children)
1615 {
1616    int newpri = set;
1617
1618    if (use_adj) newpri = getpriority(PRIO_PROCESS, pid) + adj;
1619    setpriority(PRIO_PROCESS, pid, newpri);
1620 // shouldnt need to do this as default ionice class is "none" (0), and
1621 // this inherits io priority FROM nice level
1622 //        ioprio_set(IOPRIO_WHO_PROCESS, pid,
1623 //                   IOPRIO_PRIO_VALUE(2, 5));
1624    if (do_children)
1625      {
1626         Eina_List *files;
1627         char *file, buf[PATH_MAX];
1628         FILE *f;
1629         int pid2, ppid;
1630
1631         // yes - this is /proc specific... so this may not work on some
1632         // os's - works on linux. too bad for others.
1633         files = ecore_file_ls("/proc");
1634         EINA_LIST_FREE(files, file)
1635           {
1636              if (isdigit(file[0]))
1637                {
1638                   snprintf(buf, sizeof(buf), "/proc/%s/stat", file);
1639                   f = fopen(buf, "r");
1640                   if (f)
1641                     {
1642                        pid2 = -1;
1643                        ppid = -1;
1644                        if (fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid) == 2)
1645                          {
1646                             fclose(f);
1647                             if (ppid == pid)
1648                               {
1649                                  if (adj_children)
1650                                     _pri_adj(pid2, set, adj, EINA_TRUE,
1651                                              adj_children, do_children);
1652                                  else
1653                                     _pri_adj(pid2, set, adj, use_adj,
1654                                              adj_children, do_children);
1655                               }
1656                          }
1657                        else fclose(f);
1658                     }
1659                }
1660              free(file);
1661           }
1662      }
1663 }
1664
1665 static void
1666 _e_border_pri_raise(E_Border *bd)
1667 {
1668    if (bd->client.netwm.pid <= 0) return;
1669    if (bd->client.netwm.pid == getpid()) return;
1670    _pri_adj(bd->client.netwm.pid,
1671             e_config->priority - 1, -1, EINA_FALSE,
1672 //            EINA_TRUE, EINA_TRUE);
1673             EINA_TRUE, EINA_FALSE);
1674 //   printf("WIN: pid %i, title %s (HI!!!!!!!!!!!!!!!!!!)\n",
1675 //          bd->client.netwm.pid, e_border_name_get(bd));
1676 }
1677
1678 static void
1679 _e_border_pri_norm(E_Border *bd)
1680 {
1681    if (bd->client.netwm.pid <= 0) return;
1682    if (bd->client.netwm.pid == getpid()) return;
1683    _pri_adj(bd->client.netwm.pid,
1684             e_config->priority, 1, EINA_FALSE,
1685 //            EINA_TRUE, EINA_TRUE);
1686             EINA_TRUE, EINA_FALSE);
1687 //   printf("WIN: pid %i, title %s (NORMAL)\n",
1688 //          bd->client.netwm.pid, e_border_name_get(bd));
1689 }
1690
1691 static void
1692 _e_border_frame_replace(E_Border *bd, Eina_Bool argb)
1693 {
1694    Ecore_X_Window win;
1695    Ecore_Evas *bg_ecore_evas;
1696    char buf[4096];
1697
1698    bd->argb = argb;
1699
1700    win = bd->win;
1701    bg_ecore_evas = bd->bg_ecore_evas;
1702
1703    /* unregister old frame window */
1704    eina_hash_del(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
1705    eina_hash_del(borders_hash, e_util_winid_str_get(bd->win), bd);
1706
1707    e_focus_setdown(bd);
1708    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
1709    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
1710
1711    if (bd->icon_object)
1712      evas_object_del(bd->icon_object);
1713
1714    evas_object_del(bd->bg_object);
1715    e_canvas_del(bg_ecore_evas);
1716    ecore_evas_free(bg_ecore_evas);
1717
1718    if (bd->pointer)
1719      e_object_del(E_OBJECT(bd->pointer));
1720
1721    /* create new frame */
1722    if (argb)
1723      bd->win = ecore_x_window_manager_argb_new(bd->zone->container->win,
1724                  bd->x, bd->y, bd->w, bd->h);
1725    else
1726      {
1727         bd->win = ecore_x_window_override_new(bd->zone->container->win,
1728                 bd->x, bd->y, bd->w, bd->h);
1729         ecore_x_window_shape_events_select(bd->win, 1);
1730      }
1731
1732    ecore_x_window_configure(bd->win,
1733           ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
1734           ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
1735           0, 0, 0, 0, 0,
1736           win, ECORE_X_WINDOW_STACK_BELOW);
1737
1738    e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
1739    e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
1740    e_focus_setup(bd);
1741
1742    bd->bg_ecore_evas = e_canvas_new(bd->win,
1743                                     0, 0, bd->w, bd->h, 1, 0,
1744                                     &(bd->bg_win));
1745
1746    e_canvas_add(bd->bg_ecore_evas);
1747    ecore_x_window_reparent(bd->event_win, bd->win, 0, 0);
1748
1749    bd->bg_evas = ecore_evas_get(bd->bg_ecore_evas);
1750    ecore_evas_name_class_set(bd->bg_ecore_evas, "E", "Frame_Window");
1751    ecore_evas_title_set(bd->bg_ecore_evas, "Enlightenment Frame");
1752
1753    ecore_x_window_shape_events_select(bd->bg_win, 1);
1754
1755    /* move client with shell win over to new frame */
1756    ecore_x_window_reparent(bd->client.shell_win, bd->win,
1757          bd->client_inset.l, bd->client_inset.t);
1758
1759    bd->pointer = e_pointer_window_new(bd->win, 0);
1760
1761    eina_hash_add(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
1762    eina_hash_add(borders_hash, e_util_winid_str_get(bd->win), bd);
1763
1764    if (bd->visible)
1765      {
1766         E_Border *tmp;
1767         Eina_List *l;
1768
1769         ecore_evas_show(bd->bg_ecore_evas);
1770         ecore_x_window_show(bd->win);
1771
1772         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
1773           ecore_x_window_show(tmp->win);
1774      }
1775
1776    bd->bg_object = edje_object_add(bd->bg_evas);
1777    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
1778    e_theme_edje_object_set(bd->bg_object, "base/theme/borders", buf);
1779
1780    bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
1781
1782    /* cleanup old frame */
1783    ecore_x_window_free(win);
1784 }
1785
1786 static void
1787 _e_border_client_move_resize_send(E_Border *bd)
1788 {
1789    if (bd->internal_ecore_evas)
1790      ecore_evas_managed_move(bd->internal_ecore_evas,
1791                              bd->x + bd->fx.x + bd->client_inset.l,
1792                              bd->y + bd->fx.y + bd->client_inset.t);
1793
1794    ecore_x_icccm_move_resize_send(bd->client.win,
1795                                   bd->x + bd->fx.x + bd->client_inset.l,
1796                                   bd->y + bd->fx.y + bd->client_inset.t,
1797                                   bd->client.w,
1798                                   bd->client.h);
1799 }
1800
1801 static void
1802 _e_border_pending_move_resize_add(E_Border    *bd,
1803                                   int          move,
1804                                   int          resize,
1805                                   int          x,
1806                                   int          y,
1807                                   int          w,
1808                                   int          h,
1809                                   Eina_Bool    without_border,
1810                                   unsigned int serial)
1811 {
1812    E_Border_Pending_Move_Resize *pnd;
1813
1814    pnd = E_NEW(E_Border_Pending_Move_Resize, 1);
1815    if (!pnd) return;
1816    pnd->resize = resize;
1817    pnd->move = move;
1818    pnd->without_border = without_border;
1819    pnd->x = x;
1820    pnd->y = y;
1821    pnd->w = w;
1822    pnd->h = h;
1823    pnd->serial = serial;
1824    bd->pending_move_resize = eina_list_append(bd->pending_move_resize, pnd);
1825 }
1826
1827 static void
1828 _e_border_move_internal(E_Border *bd,
1829                         int       x,
1830                         int       y,
1831                         Eina_Bool without_border)
1832 {
1833    E_Event_Border_Move *ev;
1834
1835    E_OBJECT_CHECK(bd);
1836    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1837
1838    ecore_x_window_shadow_tree_flush();
1839    if (bd->new_client)
1840      {
1841         _e_border_pending_move_resize_add(bd, 1, 0, x, y, 0, 0, without_border, 0);
1842         return;
1843      }
1844
1845    if (bd->maximized)
1846      {
1847        if ((bd->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_BOTH)
1848          {
1849             if (e_config->allow_manip)
1850               bd->maximized = 0;
1851
1852             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
1853               {
1854                   x = bd->x;
1855               }
1856             else
1857             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
1858               {
1859                   y = bd->y;
1860               }
1861          }
1862        else if (e_config->allow_manip)
1863          bd->maximized = 0;
1864        else
1865          return;
1866      }
1867
1868    if (without_border)
1869      {
1870         x -= bd->client_inset.l;
1871         y -= bd->client_inset.t;
1872      }
1873    if (bd->move_intercept_cb)
1874      {
1875         int px, py;
1876         px = bd->x, py = bd->y;
1877         bd->move_intercept_cb(bd, x, y);
1878         if ((bd->x == px) && (bd->y == py)) return;
1879      }
1880    else if ((x == bd->x) && (y == bd->y)) return;
1881    bd->pre_res_change.valid = 0;
1882    bd->x = x;
1883    bd->y = y;
1884    bd->changed = 1;
1885    bd->changes.pos = 1;
1886 #if 0
1887    if (bd->client.netwm.sync.request)
1888      {
1889         bd->client.netwm.sync.wait++;
1890         ecore_x_netwm_sync_request_send(bd->client.win, bd->client.netwm.sync.serial++);
1891      }
1892 #endif
1893    _e_border_client_move_resize_send(bd);
1894    _e_border_move_update(bd);
1895    ev = E_NEW(E_Event_Border_Move, 1);
1896    ev->border = bd;
1897    e_object_ref(E_OBJECT(bd));
1898 //  e_object_breadcrumb_add(E_OBJECT(bd), "border_move_event");
1899    ecore_event_add(E_EVENT_BORDER_MOVE, ev, _e_border_event_border_move_free, NULL);
1900    _e_border_zone_update(bd);
1901 }
1902
1903 /**
1904  * Move window to coordinates that already account border decorations.
1905  *
1906  * This call will consider given position already accounts border
1907  * decorations, so it will not be considered later. This will just
1908  * work properly with borders that have being evaluated and border
1909  * decorations are known (border->client_inset).
1910  *
1911  * @parm x horizontal position to place window.
1912  * @parm y vertical position to place window.
1913  *
1914  * @see e_border_move_without_border()
1915  */
1916 EAPI void
1917 e_border_move(E_Border *bd,
1918               int       x,
1919               int       y)
1920 {
1921    if (bd->fullscreen)
1922      return;
1923
1924    _e_border_move_internal(bd, x, y, 0);
1925 }
1926
1927
1928 /**
1929  * Set a callback which will be called just prior to updating the
1930  * move coordinates for a border
1931  */
1932 EAPI void
1933 e_border_move_intercept_cb_set(E_Border *bd, E_Border_Move_Intercept_Cb cb)
1934 {
1935    bd->move_intercept_cb = cb;
1936 }
1937
1938 /**
1939  * Move window to coordinates that do not account border decorations yet.
1940  *
1941  * This call will consider given position does not account border
1942  * decoration, so these values (border->client_inset) will be
1943  * accounted automatically. This is specially useful when it is a new
1944  * client and has not be evaluated yet, in this case
1945  * border->client_inset will be zeroed and no information is known. It
1946  * will mark pending requests so border will be accounted on
1947  * evalutation phase.
1948  *
1949  * @parm x horizontal position to place window.
1950  * @parm y vertical position to place window.
1951  *
1952  * @see e_border_move()
1953  */
1954 EAPI void
1955 e_border_move_without_border(E_Border *bd,
1956                              int       x,
1957                              int       y)
1958 {
1959    if (bd->fullscreen)
1960      return;
1961
1962    _e_border_move_internal(bd, x, y, 1);
1963 }
1964
1965 EAPI void
1966 e_border_center(E_Border *bd)
1967 {
1968    int x, y, w, h;
1969    E_OBJECT_CHECK(bd);
1970    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1971
1972    e_zone_useful_geometry_get(bd->zone, &x, &y, &w, &h);
1973    e_border_move(bd, x + (w - bd->w) / 2, y + (h - bd->h) / 2);
1974 }
1975
1976 EAPI void
1977 e_border_center_pos_get(E_Border *bd,
1978                         int      *x,
1979                         int      *y)
1980 {
1981    int zx, zy, zw, zh;
1982    E_OBJECT_CHECK(bd);
1983    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1984
1985    e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
1986    if (x) *x = zx + (zw - bd->w) / 2;
1987    if (y) *y = zy + (zh - bd->h) / 2;
1988 }
1989
1990 EAPI void
1991 e_border_fx_offset(E_Border *bd,
1992                    int       x,
1993                    int       y)
1994 {
1995    E_OBJECT_CHECK(bd);
1996    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1997
1998    if ((x == bd->fx.x) && (y == bd->fx.y)) return;
1999    bd->fx.x = x;
2000    bd->fx.y = y;
2001
2002    bd->changes.pos = 1;
2003    bd->changed = 1;
2004
2005    if (bd->moving) _e_border_move_update(bd);
2006 }
2007
2008 static void
2009 _e_border_move_resize_internal(E_Border *bd,
2010                                int       x,
2011                                int       y,
2012                                int       w,
2013                                int       h,
2014                                Eina_Bool without_border,
2015                                Eina_Bool move)
2016 {
2017    E_Event_Border_Move *mev;
2018    E_Event_Border_Resize *rev;
2019
2020    E_OBJECT_CHECK(bd);
2021    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2022
2023    ecore_x_window_shadow_tree_flush();
2024
2025    if (bd->new_client)
2026      {
2027         _e_border_pending_move_resize_add(bd, move, 1, x, y, w, h, without_border, 0);
2028         return;
2029      }
2030
2031    if (bd->maximized)
2032      {
2033        if ((bd->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_BOTH)
2034          {
2035             if (e_config->allow_manip)
2036               bd->maximized = 0;
2037
2038             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
2039               {
2040                   x = bd->x;
2041                   w = bd->w;
2042               }
2043             else
2044             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
2045               {
2046                   y = bd->y;
2047                   h = bd->h;
2048               }
2049          }
2050        else
2051        if (e_config->allow_manip)
2052          bd->maximized = 0;
2053        else
2054          return;
2055      }
2056
2057    if (without_border)
2058      {
2059         x -= bd->client_inset.l;
2060         y -= bd->client_inset.t;
2061         w += (bd->client_inset.l + bd->client_inset.r);
2062         h += (bd->client_inset.t + bd->client_inset.b);
2063      }
2064
2065    if ((!move || ((x == bd->x) && (y == bd->y))) &&
2066        (w == bd->w) && (h == bd->h))
2067      return;
2068
2069    bd->pre_res_change.valid = 0;
2070    if (move)
2071      {
2072         bd->changes.pos = 1;
2073         bd->x = x;
2074         bd->y = y;
2075      }
2076    bd->w = w;
2077    bd->h = h;
2078    bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
2079    bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
2080
2081    if ((bd->shaped) || (bd->client.shaped))
2082      {
2083         bd->need_shape_merge = 1;
2084         bd->need_shape_export = 1;
2085      }
2086    if (bd->shaped_input)
2087      {
2088         bd->need_shape_merge = 1;
2089      }
2090
2091    if (bd->internal_ecore_evas)
2092      {
2093         bd->changed = 1;
2094         bd->changes.size = 1;
2095      }
2096    else
2097      {
2098         if (bdresize && bd->client.netwm.sync.request)
2099           {
2100              bd->client.netwm.sync.wait++;
2101              /* Don't use x and y as supplied to this function, as it is called with 0, 0
2102               * when no move is intended.  The border geometry is set above anyways.
2103               */
2104              _e_border_pending_move_resize_add(bd, move, 1, bd->x, bd->y, bd->w, bd->h, without_border,
2105                                                bd->client.netwm.sync.serial);
2106              ecore_x_netwm_sync_request_send(bd->client.win,
2107                                              bd->client.netwm.sync.serial++);
2108           }
2109         else
2110           {
2111              bd->changed = 1;
2112              bd->changes.size = 1;
2113           }
2114      }
2115
2116    _e_border_client_move_resize_send(bd);
2117
2118    _e_border_resize_update(bd);
2119    if (move)
2120      {
2121         mev = E_NEW(E_Event_Border_Move, 1);
2122         mev->border = bd;
2123         e_object_ref(E_OBJECT(bd));
2124         //   e_object_breadcrumb_add(E_OBJECT(bd), "border_move_event");
2125         ecore_event_add(E_EVENT_BORDER_MOVE, mev, _e_border_event_border_move_free, NULL);
2126      }
2127
2128    rev = E_NEW(E_Event_Border_Resize, 1);
2129    rev->border = bd;
2130    e_object_ref(E_OBJECT(bd));
2131 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
2132    ecore_event_add(E_EVENT_BORDER_RESIZE, rev, _e_border_event_border_resize_free, NULL);
2133    _e_border_zone_update(bd);
2134 }
2135
2136 /**
2137  * Move and resize window to values that already account border decorations.
2138  *
2139  * This call will consider given values already accounts border
2140  * decorations, so it will not be considered later. This will just
2141  * work properly with borders that have being evaluated and border
2142  * decorations are known (border->client_inset).
2143  *
2144  * @parm x horizontal position to place window.
2145  * @parm y vertical position to place window.
2146  * @parm w horizontal window size.
2147  * @parm h vertical window size.
2148  *
2149  * @see e_border_move_resize_without_border()
2150  */
2151 EAPI void
2152 e_border_move_resize(E_Border *bd,
2153                      int       x,
2154                      int       y,
2155                      int       w,
2156                      int       h)
2157 {
2158    if (bd->fullscreen)
2159      return;
2160
2161    _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
2162 }
2163
2164 /**
2165  * Move and resize window to values that do not account border decorations yet.
2166  *
2167  * This call will consider given values already accounts border
2168  * decorations, so it will not be considered later. This will just
2169  * work properly with borders that have being evaluated and border
2170  * decorations are known (border->client_inset).
2171  *
2172  * @parm x horizontal position to place window.
2173  * @parm y vertical position to place window.
2174  * @parm w horizontal window size.
2175  * @parm h vertical window size.
2176  *
2177  * @see e_border_move_resize()
2178  */
2179 EAPI void
2180 e_border_move_resize_without_border(E_Border *bd,
2181                                     int       x,
2182                                     int       y,
2183                                     int       w,
2184                                     int       h)
2185 {
2186    if (bd->fullscreen)
2187      return;
2188
2189    _e_border_move_resize_internal(bd, x, y, w, h, 1, 1);
2190 }
2191
2192 /**
2193  * Resize window to values that already account border decorations.
2194  *
2195  * This call will consider given size already accounts border
2196  * decorations, so it will not be considered later. This will just
2197  * work properly with borders that have being evaluated and border
2198  * decorations are known (border->client_inset).
2199  *
2200  * @parm w horizontal window size.
2201  * @parm h vertical window size.
2202  *
2203  * @see e_border_resize_without_border()
2204  */
2205 EAPI void
2206 e_border_resize(E_Border *bd,
2207                 int       w,
2208                 int       h)
2209 {
2210    if (bd->fullscreen)
2211      return;
2212
2213    _e_border_move_resize_internal(bd, 0, 0, w, h, 0, 0);
2214 }
2215
2216 /**
2217  * Resize window to values that do not account border decorations yet.
2218  *
2219  * This call will consider given size does not account border
2220  * decoration, so these values (border->client_inset) will be
2221  * accounted automatically. This is specially useful when it is a new
2222  * client and has not be evaluated yet, in this case
2223  * border->client_inset will be zeroed and no information is known. It
2224  * will mark pending requests so border will be accounted on
2225  * evalutation phase.
2226  *
2227  * @parm w horizontal window size.
2228  * @parm h vertical window size.
2229  *
2230  * @see e_border_resize()
2231  */
2232 EAPI void
2233 e_border_resize_without_border(E_Border *bd,
2234                                int       w,
2235                                int       h)
2236 {
2237    if (bd->fullscreen)
2238      return;
2239
2240    _e_border_move_resize_internal(bd, 0, 0, w, h, 1, 0);
2241 }
2242
2243 EAPI void
2244 e_border_layer_set(E_Border *bd,
2245                    int       layer)
2246 {
2247    int oldraise;
2248
2249    E_OBJECT_CHECK(bd);
2250    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2251
2252    ecore_x_window_shadow_tree_flush();
2253
2254    oldraise = e_config->transient.raise;
2255
2256    if (bd->fullscreen)
2257      {
2258         bd->saved.layer = layer;
2259         return;
2260      }
2261    bd->layer = layer;
2262    if (e_config->transient.layer)
2263      {
2264         Eina_List *l;
2265         E_Border *child;
2266         Eina_List *list = _e_border_sub_borders_new(bd);
2267
2268         /* We need to set raise to one, else the child wont
2269          * follow to the new layer. It should be like this,
2270          * even if the user usually doesn't want to raise
2271          * the transients.
2272          */
2273         e_config->transient.raise = 1;
2274         EINA_LIST_FOREACH(list, l, child)
2275           {
2276              e_border_layer_set(child, layer);
2277           }
2278      }
2279    e_border_raise(bd);
2280    e_config->transient.raise = oldraise;
2281 }
2282
2283 EAPI void
2284 e_border_raise(E_Border *bd)
2285 {
2286    E_Event_Border_Stack *ev;
2287    E_Border *last = NULL, *child;
2288    Eina_List *l;
2289
2290    E_OBJECT_CHECK(bd);
2291    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2292
2293    ecore_x_window_shadow_tree_flush();
2294
2295    if (e_config->transient.raise)
2296      {
2297 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2298         if (e_config->focus_setting != E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
2299           {
2300 #endif
2301         Eina_List *list = _e_border_sub_borders_new(bd);
2302
2303         EINA_LIST_REVERSE_FOREACH(list, l, child)
2304           {
2305              /* Don't stack iconic transients. If the user wants these shown,
2306               * thats another option.
2307               */
2308              if (!child->iconic)
2309                {
2310                   if (last)
2311                     e_border_stack_below(child, last);
2312                   else
2313                     {
2314                        E_Border *above;
2315
2316                        /* First raise the border to find out which border we will end up above */
2317                        above = e_container_border_raise(child);
2318
2319                        if (above)
2320                          {
2321                             /* We ended up above a border, now we must stack this border to
2322                              * generate the stacking event, and to check if this transient
2323                              * has other transients etc.
2324                              */
2325                             e_border_stack_above(child, above);
2326                          }
2327                        else
2328                          {
2329                             /* If we didn't end up above any border, we are on the bottom! */
2330                             e_border_lower(child);
2331                          }
2332                     }
2333                   last = child;
2334                }
2335           }
2336         eina_list_free(list);
2337 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2338           }
2339         else
2340           {
2341              EINA_LIST_FOREACH(bd->transients, l, child)
2342                {
2343                 /* Don't stack iconic transients. If the user wants these shown,
2344                  * thats another option.
2345                  */
2346                   if (!child->iconic)
2347                     {
2348                        child->layer = bd->layer;
2349                        if (!last) last = child;
2350                        e_border_raise (child);
2351                     }
2352                }
2353           }
2354 #endif
2355      }
2356
2357    ev = E_NEW(E_Event_Border_Stack, 1);
2358    ev->border = bd;
2359    e_object_ref(E_OBJECT(bd));
2360
2361    if (last)
2362      {
2363         e_container_border_stack_below(bd, last);
2364         ev->stack = last;
2365         e_object_ref(E_OBJECT(last));
2366         ev->type = E_STACKING_BELOW;
2367      }
2368    else
2369      {
2370         E_Border *above;
2371
2372         /* If we don't have any children, raise this border */
2373         above = e_container_border_raise(bd);
2374         e_border_raise_latest_set(bd);
2375         if (above)
2376           {
2377              /* We ended up above a border */
2378               ev->stack = above;
2379               e_object_ref(E_OBJECT(above));
2380               ev->type = E_STACKING_ABOVE;
2381           }
2382         else
2383           {
2384              /* No border to raise above, same as a lower! */
2385               ev->stack = NULL;
2386               ev->type = E_STACKING_ABOVE;
2387           }
2388      }
2389
2390    ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2391    e_remember_update(bd);
2392 }
2393
2394 EAPI void
2395 e_border_lower(E_Border *bd)
2396 {
2397    E_Event_Border_Stack *ev;
2398    E_Border *last = NULL, *child;
2399    Eina_List *l;
2400
2401    E_OBJECT_CHECK(bd);
2402    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2403
2404    ecore_x_window_shadow_tree_flush();
2405
2406    if (e_config->transient.lower)
2407      {
2408 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2409         if (e_config->focus_setting != E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
2410           {
2411 #endif
2412         Eina_List *list = _e_border_sub_borders_new(bd);
2413
2414         EINA_LIST_REVERSE_FOREACH(list, l, child)
2415           {
2416              /* Don't stack iconic transients. If the user wants these shown,
2417               * thats another option.
2418               */
2419              if (!child->iconic)
2420                {
2421                   if (last)
2422                     e_border_stack_below(child, last);
2423                   else
2424                     {
2425                        E_Border *below;
2426
2427                        /* First lower the border to find out which border we will end up below */
2428                        below = e_container_border_lower(child);
2429
2430                        if (below)
2431                          {
2432                             /* We ended up below a border, now we must stack this border to
2433                              * generate the stacking event, and to check if this transient
2434                              * has other transients etc.
2435                              */
2436                             e_border_stack_below(child, below);
2437                          }
2438                        else
2439                          {
2440                             /* If we didn't end up below any border, we are on top! */
2441                             e_border_raise(child);
2442                          }
2443                     }
2444                   last = child;
2445                }
2446           }
2447         eina_list_free(list);
2448
2449 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2450           }
2451         else
2452           {
2453              EINA_LIST_FOREACH(bd->transients, l, child)
2454                {
2455                 /* Don't stack iconic transients. If the user wants these shown,
2456                  * thats another option.
2457                  */
2458                   if (!child->iconic)
2459                     {
2460                        child->layer = bd->layer;
2461                        e_border_lower (child);
2462                        last = child;
2463                     }
2464                }
2465           }
2466 #endif
2467      }
2468
2469    ev = E_NEW(E_Event_Border_Stack, 1);
2470    ev->border = bd;
2471    e_object_ref(E_OBJECT(bd));
2472
2473    if (last)
2474      {
2475         e_container_border_stack_below(bd, last);
2476         ev->stack = last;
2477         e_object_ref(E_OBJECT(last));
2478         ev->type = E_STACKING_BELOW;
2479      }
2480    else
2481      {
2482         E_Border *below;
2483
2484         /* If we don't have any children, lower this border */
2485         below = e_container_border_lower(bd);
2486         if (below)
2487           {
2488              /* We ended up below a border */
2489               ev->stack = below;
2490               e_object_ref(E_OBJECT(below));
2491               ev->type = E_STACKING_BELOW;
2492           }
2493         else
2494           {
2495              /* No border to hide under, same as a raise! */
2496               ev->stack = NULL;
2497               ev->type = E_STACKING_BELOW;
2498           }
2499      }
2500
2501    ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2502    e_remember_update(bd);
2503 }
2504
2505 EAPI void
2506 e_border_stack_above(E_Border *bd,
2507                      E_Border *above)
2508 {
2509    /* TODO: Should stack above allow the border to change level */
2510     E_Event_Border_Stack *ev;
2511     E_Border *last = NULL, *child;
2512     Eina_List *l;
2513
2514     E_OBJECT_CHECK(bd);
2515     E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2516
2517     ecore_x_window_shadow_tree_flush();
2518
2519     if (e_config->transient.raise)
2520       {
2521          Eina_List *list = _e_border_sub_borders_new(bd);
2522
2523          EINA_LIST_REVERSE_FOREACH(list, l, child)
2524            {
2525               /* Don't stack iconic transients. If the user wants these shown,
2526                * thats another option.
2527                */
2528               if (!child->iconic)
2529                 {
2530                    if (last)
2531                      e_border_stack_below(child, last);
2532                    else
2533                      e_border_stack_above(child, above);
2534                    last = child;
2535                 }
2536            }
2537          eina_list_free(list);
2538       }
2539
2540     ev = E_NEW(E_Event_Border_Stack, 1);
2541     ev->border = bd;
2542     e_object_ref(E_OBJECT(bd));
2543
2544     if (last)
2545       {
2546          e_container_border_stack_below(bd, last);
2547          ev->stack = last;
2548          e_object_ref(E_OBJECT(last));
2549          ev->type = E_STACKING_BELOW;
2550       }
2551     else
2552       {
2553          e_container_border_stack_above(bd, above);
2554          ev->stack = above;
2555          e_object_ref(E_OBJECT(above));
2556          ev->type = E_STACKING_ABOVE;
2557       }
2558
2559     ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2560     e_remember_update(bd);
2561 }
2562
2563 EAPI void
2564 e_border_stack_below(E_Border *bd,
2565                      E_Border *below)
2566 {
2567    /* TODO: Should stack below allow the border to change level */
2568     E_Event_Border_Stack *ev;
2569     E_Border *last = NULL, *child;
2570     Eina_List *l;
2571
2572     E_OBJECT_CHECK(bd);
2573     E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2574
2575     ecore_x_window_shadow_tree_flush();
2576
2577     if (e_config->transient.lower)
2578       {
2579          Eina_List *list = _e_border_sub_borders_new(bd);
2580
2581          EINA_LIST_REVERSE_FOREACH(bd->transients, l, child)
2582            {
2583               /* Don't stack iconic transients. If the user wants these shown,
2584                * thats another option.
2585                */
2586               if (!child->iconic)
2587                 {
2588                    if (last)
2589                      e_border_stack_below(child, last);
2590                    else
2591                      e_border_stack_below(child, below);
2592                    last = child;
2593                 }
2594            }
2595          eina_list_free(list);
2596       }
2597
2598     ev = E_NEW(E_Event_Border_Stack, 1);
2599     ev->border = bd;
2600     e_object_ref(E_OBJECT(bd));
2601
2602     if (last)
2603       {
2604          e_container_border_stack_below(bd, last);
2605          ev->stack = last;
2606          e_object_ref(E_OBJECT(last));
2607          ev->type = E_STACKING_BELOW;
2608       }
2609     else
2610       {
2611          e_container_border_stack_below(bd, below);
2612          ev->stack = below;
2613          e_object_ref(E_OBJECT(below));
2614          ev->type = E_STACKING_BELOW;
2615       }
2616
2617     ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2618     e_remember_update(bd);
2619 }
2620
2621 EAPI void
2622 e_border_focus_latest_set(E_Border *bd)
2623 {
2624    focus_stack = eina_list_remove(focus_stack, bd);
2625    focus_stack = eina_list_prepend(focus_stack, bd);
2626 }
2627
2628 EAPI void
2629 e_border_raise_latest_set(E_Border *bd)
2630 {
2631    raise_stack = eina_list_remove(raise_stack, bd);
2632    raise_stack = eina_list_prepend(raise_stack, bd);
2633 }
2634
2635 /*
2636  * Sets the focus to the given border if necessary
2637  * There are 3 cases of different focus_policy-configurations:
2638  *
2639  * - E_FOCUS_CLICK: just set the focus, the most simple one
2640  *
2641  * - E_FOCUS_MOUSE: focus is where the mouse is, so try to
2642  *   warp the pointer to the window. If this fails (because
2643  *   the pointer is already in the window), just set the focus.
2644  *
2645  * - E_FOCUS_SLOPPY: focus is where the mouse is or on the
2646  *   last window which was focused, if the mouse is on the
2647  *   desktop. So, we need to look if there is another window
2648  *   under the pointer and warp to pointer to the right
2649  *   one if so (also, we set the focus afterwards). In case
2650  *   there is no window under pointer, the pointer is on the
2651  *   desktop and so we just set the focus.
2652  *
2653  *
2654  * This function is to be called when setting the focus was not
2655  * explicitly triggered by the user (by moving the mouse or
2656  * clicking for example), but implicitly (by closing a window,
2657  * the last focused window should get focus).
2658  *
2659  */
2660 EAPI void
2661 e_border_focus_set_with_pointer(E_Border *bd)
2662 {
2663 #ifdef PRINT_LOTS_OF_DEBUG
2664    E_PRINT_BORDER_INFO(bd);
2665 #endif
2666    /* note: this is here as it seems there are enough apps that do not even
2667     * expect us to emulate a look of focus but not actually set x input
2668     * focus as we do - so simply abort any focuse set on such windows */
2669    /* be strict about accepting focus hint */
2670    if ((!bd->client.icccm.accepts_focus) &&
2671        (!bd->client.icccm.take_focus)) return;
2672    if (bd->lock_focus_out) return;
2673
2674    e_border_focus_set(bd, 1, 1);
2675
2676    if (e_config->focus_policy == E_FOCUS_CLICK) return;
2677    if (!bd->visible) return;
2678
2679    if (e_config->focus_policy == E_FOCUS_SLOPPY)
2680      {
2681         if (!e_border_under_pointer_get(bd->desk, bd))
2682           {
2683              e_border_pointer_warp_to_center(bd);
2684           }
2685      }
2686    else
2687      {
2688         e_border_pointer_warp_to_center(bd);
2689      }
2690 }
2691
2692 EAPI void
2693 e_border_focus_set(E_Border *bd,
2694                    int       focus,
2695                    int       set)
2696 {
2697    E_Border *bd_unfocus = NULL;
2698    Eina_Bool focus_changed = EINA_FALSE;
2699
2700    E_OBJECT_CHECK(bd);
2701    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2702    /* note: this is here as it seems there are enough apps that do not even
2703     * expect us to emulate a look of focus but not actually set x input
2704     * focus as we do - so simply abort any focuse set on such windows */
2705    /* be strict about accepting focus hint */
2706    if ((!bd->client.icccm.accepts_focus) &&
2707        (!bd->client.icccm.take_focus))
2708      return;
2709    if ((set) && (focus) && (bd->lock_focus_out)) return;
2710    
2711    /* dont focus an iconified window. that's silly! */
2712    if (focus)
2713      {
2714         if (bd->iconic)
2715           {
2716              e_border_uniconify(bd);
2717              if (!focus_track_frozen)
2718                e_border_focus_latest_set(bd);
2719              return;
2720           }
2721         else if (!bd->visible)
2722           {
2723              return;
2724           }
2725         /* FIXME: hack for deskflip animation:
2726          * dont update focus when sliding previous desk */
2727         else if ((!bd->sticky) &&
2728                  (bd->desk != e_desk_current_get(bd->desk->zone)))
2729           {
2730              return;
2731           }
2732      }
2733
2734    if ((bd->modal) && (bd->modal != bd) && (bd->modal->visible))
2735      {
2736         e_border_focus_set(bd->modal, focus, set);
2737         return;
2738      }
2739    else if ((bd->leader) && (bd->leader->modal) && (bd->leader->modal != bd))
2740      {
2741         e_border_focus_set(bd->leader->modal, focus, set);
2742         return;
2743      }
2744
2745    if (focus)
2746      {
2747         if (set)
2748           {
2749              if (bd->visible && bd->changes.visible)
2750                {
2751                   bd->want_focus = 1;
2752                   bd->changed = 1;
2753                }
2754              else if ((!bd->focused) ||
2755                       (focus_next && (bd != eina_list_data_get(focus_next))))
2756                {
2757                   Eina_List *l;
2758
2759                   if ((l = eina_list_data_find_list(focus_next, bd)))
2760                     focus_next = eina_list_promote_list(focus_next, l);
2761                   else
2762                     focus_next = eina_list_prepend(focus_next, bd);
2763                }
2764              if ((bd->client.icccm.take_focus) &&
2765                  (bd->client.icccm.accepts_focus))
2766                {
2767                   e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
2768                   /* TODO what if the client didn't take focus ? */
2769                }
2770              else if (!bd->client.icccm.accepts_focus)
2771                {
2772                   e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
2773                }
2774              else if (!bd->client.icccm.take_focus)
2775                {
2776                   e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
2777                   /* e_border_focus_set(bd, 1, 0); */
2778                }
2779             return;
2780           }
2781
2782         if (!bd->focused)
2783           {
2784              Eina_List *l;
2785              E_Border *bd2;
2786              
2787              if (focused) bd_unfocus = focused;
2788              if (focusing == bd) focusing = NULL;
2789              bd->focused = 1;
2790              focused = bd;
2791              if (!bd_unfocus)
2792                {
2793                   EINA_LIST_FOREACH(e_border_client_list(), l, bd2)
2794                     {
2795                        if ((bd2->fullscreen) &&
2796                            (bd2 != bd) &&
2797                            (bd2->zone == bd->zone) &&
2798                            ((bd2->desk == bd->desk) ||
2799                                (bd2->sticky) || (bd->sticky)))
2800                          {
2801                             Eina_Bool unfocus_is_parent = EINA_FALSE;
2802                             E_Border *bd_parent;
2803                             
2804                             bd_parent = bd->parent;
2805                             while (bd_parent)
2806                               {
2807                                  if (bd_parent == bd2)
2808                                    {
2809                                       unfocus_is_parent = EINA_TRUE;
2810                                       break;
2811                                    }
2812                                  bd_parent = bd->parent;
2813                               }
2814                             if ((!unfocus_is_parent) && 
2815                                 (!e_config->allow_above_fullscreen))
2816                               {
2817                                  e_border_iconify(bd2);
2818                               }
2819                          }
2820                     }
2821                }
2822              focus_changed = EINA_TRUE;
2823           }
2824      }
2825    else
2826      {
2827         bd->want_focus = 0;
2828         focus_next = eina_list_remove(focus_next, bd);
2829         if (bd == focusing) focusing = NULL;
2830
2831         if ((bd->focused) && 
2832             ((bd->desk == e_desk_current_get(bd->zone)) || (bd->sticky)))
2833           {
2834              Eina_Bool wasfocused = EINA_FALSE;
2835              bd_unfocus = bd;
2836
2837              /* should always be the case. anyway */
2838              if (bd == focused)
2839                {
2840                   focused = NULL;
2841                   wasfocused = EINA_TRUE;
2842                }
2843
2844              if ((set) && (!focus_next) && (!focusing))
2845                {
2846                   e_grabinput_focus(bd->zone->container->bg_win,
2847                                     E_FOCUS_METHOD_PASSIVE);
2848                }
2849              if ((bd->fullscreen) && (wasfocused))
2850                {
2851                   Eina_Bool have_vis_child = EINA_FALSE;
2852                   Eina_List *l;
2853                   E_Border *bd2;
2854                   
2855                   EINA_LIST_FOREACH(e_border_client_list(), l, bd2)
2856                     {
2857                        if ((bd2 != bd) &&
2858                            (bd2->zone == bd->zone) &&
2859                            ((bd2->desk == bd->desk) ||
2860                                (bd2->sticky) || (bd->sticky)))
2861                          {
2862                             if (bd2->parent == bd)
2863                               {
2864                                  have_vis_child = EINA_TRUE;
2865                                  break;
2866                               }
2867                          }
2868                     }
2869                   if ((!have_vis_child) && 
2870                       (!e_config->allow_above_fullscreen))
2871                     e_border_iconify(bd);
2872                }
2873           }
2874      }
2875    
2876    if ((bd_unfocus) &&
2877        (!e_object_is_del(E_OBJECT(bd_unfocus)) &&
2878         (e_object_ref_get(E_OBJECT(bd_unfocus)) > 0)))
2879      {
2880         E_Event_Border_Focus_Out *ev;
2881
2882         bd_unfocus->focused = 0;
2883         e_focus_event_focus_out(bd_unfocus);
2884
2885         if (bd_unfocus->raise_timer)
2886           ecore_timer_del(bd_unfocus->raise_timer);
2887         bd_unfocus->raise_timer = NULL;
2888
2889         edje_object_signal_emit(bd_unfocus->bg_object, "e,state,unfocused", "e");
2890         if (bd_unfocus->icon_object)
2891           edje_object_signal_emit(bd_unfocus->icon_object, "e,state,unfocused", "e");
2892
2893         ev = E_NEW(E_Event_Border_Focus_Out, 1);
2894         ev->border = bd_unfocus;
2895         e_object_ref(E_OBJECT(bd_unfocus));
2896
2897         ecore_event_add(E_EVENT_BORDER_FOCUS_OUT, ev,
2898                         _e_border_event_border_focus_out_free, NULL);
2899         if ((bd_unfocus->fullscreen) &&
2900             (bd != bd_unfocus) &&
2901             (bd->zone == bd_unfocus->zone) &&
2902             ((bd->desk == bd_unfocus->desk) ||
2903              (bd->sticky) || (bd_unfocus->sticky)))
2904           {
2905              Eina_Bool unfocus_is_parent = EINA_FALSE;
2906              E_Border *bd_parent;
2907
2908              bd_parent = bd->parent;
2909              while (bd_parent)
2910                {
2911                   if (bd_parent == bd_unfocus)
2912                     {
2913                        unfocus_is_parent = EINA_TRUE;
2914                        break;
2915                     }
2916                   bd_parent = bd->parent;
2917                }
2918              if ((!unfocus_is_parent) && (!e_config->allow_above_fullscreen))
2919                {
2920                   e_border_iconify(bd_unfocus);
2921                }
2922           }
2923      }
2924
2925    if (focus_changed)
2926      {
2927         E_Event_Border_Focus_In *ev;
2928
2929         e_focus_event_focus_in(bd);
2930
2931         if (!focus_track_frozen)
2932           e_border_focus_latest_set(bd);
2933
2934         e_hints_active_window_set(bd->zone->container->manager, bd);
2935
2936         edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
2937         if (bd->icon_object)
2938           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
2939
2940         ev = E_NEW(E_Event_Border_Focus_In, 1);
2941         ev->border = bd;
2942         e_object_ref(E_OBJECT(bd));
2943
2944         ecore_event_add(E_EVENT_BORDER_FOCUS_IN, ev,
2945                         _e_border_event_border_focus_in_free, NULL);
2946      }
2947 }
2948
2949 EAPI void
2950 e_border_shade(E_Border   *bd,
2951                E_Direction dir)
2952 {
2953    E_Event_Border_Resize *ev;
2954    Eina_List *l;
2955    E_Border *tmp;
2956
2957    E_OBJECT_CHECK(bd);
2958    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2959    if ((bd->shaded) || (bd->shading) || (bd->fullscreen) ||
2960        ((bd->maximized) && (!e_config->allow_manip))) return;
2961    if ((bd->client.border.name) &&
2962        (!strcmp("borderless", bd->client.border.name))) return;
2963
2964    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
2965      ecore_x_window_hide(tmp->win);
2966
2967    ecore_x_window_shadow_tree_flush();
2968
2969    bd->shade.x = bd->x;
2970    bd->shade.y = bd->y;
2971    bd->shade.dir = dir;
2972
2973    e_hints_window_shaded_set(bd, 1);
2974    e_hints_window_shade_direction_set(bd, dir);
2975
2976    if (e_config->border_shade_animate)
2977      {
2978         bd->shade.start = ecore_loop_time_get();
2979         bd->shading = 1;
2980         bd->changes.shading = 1;
2981         bd->changed = 1;
2982
2983         if (bd->shade.dir == E_DIRECTION_UP ||
2984             bd->shade.dir == E_DIRECTION_LEFT)
2985           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
2986         else
2987           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NE);
2988
2989         bd->shade.anim = ecore_animator_add(_e_border_shade_animator, bd);
2990         edje_object_signal_emit(bd->bg_object, "e,state,shading", "e");
2991      }
2992    else
2993      {
2994         if (bd->shade.dir == E_DIRECTION_UP)
2995           {
2996              bd->h = bd->client_inset.t + bd->client_inset.b;
2997           }
2998         else if (bd->shade.dir == E_DIRECTION_DOWN)
2999           {
3000              bd->h = bd->client_inset.t + bd->client_inset.b;
3001              bd->y = bd->y + bd->client.h;
3002              bd->changes.pos = 1;
3003           }
3004         else if (bd->shade.dir == E_DIRECTION_LEFT)
3005           {
3006              bd->w = bd->client_inset.l + bd->client_inset.r;
3007           }
3008         else if (bd->shade.dir == E_DIRECTION_RIGHT)
3009           {
3010              bd->w = bd->client_inset.l + bd->client_inset.r;
3011              bd->x = bd->x + bd->client.w;
3012              bd->changes.pos = 1;
3013           }
3014
3015         if ((bd->shaped) || (bd->client.shaped))
3016           {
3017              bd->need_shape_merge = 1;
3018              bd->need_shape_export = 1;
3019           }
3020         if (bd->shaped_input)
3021           {
3022              bd->need_shape_merge = 1;
3023           }
3024
3025         bd->changes.size = 1;
3026         bd->shaded = 1;
3027         bd->changes.shaded = 1;
3028         bd->changed = 1;
3029         edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
3030         e_border_frame_recalc(bd);
3031         ev = E_NEW(E_Event_Border_Resize, 1);
3032         ev->border = bd;
3033         /* The resize is added in the animator when animation complete */
3034         /* For non-animated, we add it immediately with the new size */
3035         e_object_ref(E_OBJECT(bd));
3036         //           e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
3037         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
3038      }
3039
3040    e_remember_update(bd);
3041 }
3042
3043 EAPI void
3044 e_border_unshade(E_Border   *bd,
3045                  E_Direction dir)
3046 {
3047    E_Event_Border_Resize *ev;
3048    Eina_List *l;
3049    E_Border *tmp;
3050
3051    E_OBJECT_CHECK(bd);
3052    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3053    if ((!bd->shaded) || (bd->shading))
3054      return;
3055
3056    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
3057      ecore_x_window_show(tmp->win);
3058
3059    ecore_x_window_shadow_tree_flush();
3060
3061    bd->shade.dir = dir;
3062
3063    e_hints_window_shaded_set(bd, 0);
3064    e_hints_window_shade_direction_set(bd, dir);
3065
3066    if (bd->shade.dir == E_DIRECTION_UP ||
3067        bd->shade.dir == E_DIRECTION_LEFT)
3068      {
3069         bd->shade.x = bd->x;
3070         bd->shade.y = bd->y;
3071      }
3072    else
3073      {
3074         bd->shade.x = bd->x - bd->client.w;
3075         bd->shade.y = bd->y - bd->client.h;
3076      }
3077    if (e_config->border_shade_animate)
3078      {
3079         bd->shade.start = ecore_loop_time_get();
3080         bd->shading = 1;
3081         bd->changes.shading = 1;
3082         bd->changed = 1;
3083
3084         if (bd->shade.dir == E_DIRECTION_UP)
3085           {
3086              ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
3087              ecore_x_window_move_resize(bd->client.win, 0,
3088                                         bd->h - (bd->client_inset.t + bd->client_inset.b) -
3089                                         bd->client.h,
3090                                         bd->client.w, bd->client.h);
3091           }
3092         else if (bd->shade.dir == E_DIRECTION_LEFT)
3093           {
3094              ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
3095              ecore_x_window_move_resize(bd->client.win,
3096                                         bd->w - (bd->client_inset.l + bd->client_inset.r) -
3097                                         bd->client.h,
3098                                         0, bd->client.w, bd->client.h);
3099           }
3100         else
3101           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NE);
3102
3103         bd->shade.anim = ecore_animator_add(_e_border_shade_animator, bd);
3104         edje_object_signal_emit(bd->bg_object, "e,state,unshading", "e");
3105      }
3106    else
3107      {
3108         if (bd->shade.dir == E_DIRECTION_UP)
3109           {
3110              bd->h = bd->client_inset.t + bd->client.h + bd->client_inset.b;
3111           }
3112         else if (bd->shade.dir == E_DIRECTION_DOWN)
3113           {
3114              bd->h = bd->client_inset.t + bd->client.h + bd->client_inset.b;
3115              bd->y = bd->y - bd->client.h;
3116              bd->changes.pos = 1;
3117           }
3118         else if (bd->shade.dir == E_DIRECTION_LEFT)
3119           {
3120              bd->w = bd->client_inset.l + bd->client.w + bd->client_inset.r;
3121           }
3122         else if (bd->shade.dir == E_DIRECTION_RIGHT)
3123           {
3124              bd->w = bd->client_inset.l + bd->client.w + bd->client_inset.r;
3125              bd->x = bd->x - bd->client.w;
3126              bd->changes.pos = 1;
3127           }
3128         if ((bd->shaped) || (bd->client.shaped))
3129           {
3130              bd->need_shape_merge = 1;
3131              bd->need_shape_export = 1;
3132           }
3133         if (bd->shaped_input)
3134           {
3135              bd->need_shape_merge = 1;
3136           }
3137
3138         bd->changes.size = 1;
3139         bd->shaded = 0;
3140         bd->changes.shaded = 1;
3141         bd->changed = 1;
3142         edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
3143         e_border_frame_recalc(bd);
3144         ev = E_NEW(E_Event_Border_Resize, 1);
3145         ev->border = bd;
3146         /* The resize is added in the animator when animation complete */
3147         /* For non-animated, we add it immediately with the new size */
3148         e_object_ref(E_OBJECT(bd));
3149         //           e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
3150         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
3151      }
3152
3153    e_remember_update(bd);
3154 }
3155
3156 static void
3157 _e_border_client_inset_calc(E_Border *bd)
3158 {
3159    /* int w, h; */
3160    Evas_Coord cx, cy, cw, ch;
3161
3162    if (bd->bg_object)
3163      {
3164         evas_object_resize(bd->bg_object, 1000, 1000);
3165         edje_object_message_signal_process(bd->bg_object);
3166         edje_object_calc_force(bd->bg_object);
3167         edje_object_part_geometry_get(bd->bg_object, "e.swallow.client", &cx, &cy, &cw, &ch);
3168         bd->client_inset.l = cx;
3169         bd->client_inset.r = 1000 - (cx + cw);
3170         bd->client_inset.t = cy;
3171         bd->client_inset.b = 1000 - (cy + ch);
3172      }
3173    else
3174      {
3175         bd->client_inset.l = 0;
3176         bd->client_inset.r = 0;
3177         bd->client_inset.t = 0;
3178         bd->client_inset.b = 0;
3179      }
3180
3181    ecore_x_netwm_frame_size_set(bd->client.win,
3182                                 bd->client_inset.l, bd->client_inset.r,
3183                                 bd->client_inset.t, bd->client_inset.b);
3184    ecore_x_e_frame_size_set(bd->client.win,
3185                             bd->client_inset.l, bd->client_inset.r,
3186                             bd->client_inset.t, bd->client_inset.b);
3187 }
3188
3189 static void
3190 _e_border_maximize(E_Border *bd, E_Maximize max)
3191 {
3192    int x1, yy1, x2, y2;
3193    int w, h, pw, ph;
3194    int zx, zy, zw, zh;
3195 #ifdef _F_USE_BOTTOM_TOP_MAXIMIZE
3196    int cy = 0;
3197 #endif
3198
3199    zx = zy = zw = zh = 0;
3200
3201    switch (max & E_MAXIMIZE_TYPE)
3202      {
3203       case E_MAXIMIZE_NONE:
3204          /* Ignore */
3205          break;
3206
3207       case E_MAXIMIZE_FULLSCREEN:
3208          w = bd->zone->w;
3209          h = bd->zone->h;
3210
3211          if (bd->bg_object)
3212            {
3213               edje_object_signal_emit(bd->bg_object, "e,action,maximize,fullscreen", "e");
3214               _e_border_client_inset_calc(bd);
3215            }
3216          e_border_resize_limit(bd, &w, &h);
3217          /* center x-direction */
3218          x1 = bd->zone->x + (bd->zone->w - w) / 2;
3219          /* center y-direction */
3220          yy1 = bd->zone->y + (bd->zone->h - h) / 2;
3221
3222 #ifdef _F_USE_BOTTOM_TOP_MAXIMIZE
3223          cy = bd->zone->y + (bd->zone->h / 2);
3224 #endif
3225
3226          switch (max & E_MAXIMIZE_DIRECTION)
3227            {
3228             case E_MAXIMIZE_BOTH:
3229               e_border_move_resize(bd, x1, yy1, w, h);
3230               break;
3231
3232             case E_MAXIMIZE_VERTICAL:
3233               e_border_move_resize(bd, bd->x, yy1, bd->w, h);
3234               break;
3235
3236             case E_MAXIMIZE_HORIZONTAL:
3237               e_border_move_resize(bd, x1, bd->y, w, bd->h);
3238               break;
3239
3240             case E_MAXIMIZE_LEFT:
3241               e_border_move_resize(bd, bd->zone->x, bd->zone->y, w / 2, h);
3242               break;
3243
3244             case E_MAXIMIZE_RIGHT:
3245               e_border_move_resize(bd, x1, bd->zone->y, w / 2, h);
3246               break;
3247 #ifdef _F_USE_BOTTOM_TOP_MAXIMIZE
3248             case E_MAXIMIZE_TOP:
3249               e_border_move_resize(bd, bd->zone->x, bd->zone->y, w, h / 2);
3250               break;
3251             case E_MAXIMIZE_BOTTOM:
3252               e_border_move_resize(bd, bd->zone->x, cy, w, h / 2);
3253               break;
3254 #endif
3255            }
3256          break;
3257
3258       case E_MAXIMIZE_SMART:
3259       case E_MAXIMIZE_EXPAND:
3260          if (bd->zone)
3261            e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
3262
3263          if (bd->w < zw)
3264            w = bd->w;
3265          else
3266            w = zw;
3267
3268          if (bd->h < zh)
3269            h = bd->h;
3270          else
3271            h = zh;
3272
3273          if (bd->x < zx) // window left not useful coordinates
3274            x1 = zx;
3275          else if (bd->x + bd->w > zx + zw) // window right not useful coordinates
3276            x1 = zx + zw - bd->w;
3277          else // window normal position
3278            x1 = bd->x;
3279
3280          if (bd->y < zy) // window top not useful coordinates
3281            yy1 = zy;
3282          else if (bd->y + bd->h > zy + zh) // window bottom not useful coordinates
3283            yy1 = zy + zh - bd->h;
3284          else // window normal position
3285            yy1 = bd->y;
3286
3287          switch (max & E_MAXIMIZE_DIRECTION)
3288            {
3289             case E_MAXIMIZE_BOTH:
3290               e_border_move_resize(bd, zx, zy, zw, zh);
3291               break;
3292
3293             case E_MAXIMIZE_VERTICAL:
3294               e_border_move_resize(bd, x1, zy, w, zh);
3295               break;
3296
3297             case E_MAXIMIZE_HORIZONTAL:
3298               e_border_move_resize(bd, zx, yy1, zw, h);
3299               break;
3300
3301             case E_MAXIMIZE_LEFT:
3302               e_border_move_resize(bd, zx, zy, zw / 2, zh);
3303               break;
3304
3305             case E_MAXIMIZE_RIGHT:
3306               e_border_move_resize(bd, zx + zw / 2, zy, zw / 2, zh);
3307               break;
3308            }
3309
3310          edje_object_signal_emit(bd->bg_object, "e,action,maximize", "e");
3311          break;
3312
3313       case E_MAXIMIZE_FILL:
3314          x1 = bd->zone->x;
3315          yy1 = bd->zone->y;
3316          x2 = bd->zone->x + bd->zone->w;
3317          y2 = bd->zone->y + bd->zone->h;
3318
3319          /* walk through all shelves */
3320          e_maximize_border_shelf_fill(bd, &x1, &yy1, &x2, &y2, max);
3321
3322          /* walk through all windows */
3323          e_maximize_border_border_fill(bd, &x1, &yy1, &x2, &y2, max);
3324
3325          w = x2 - x1;
3326          h = y2 - yy1;
3327          pw = w;
3328          ph = h;
3329          e_border_resize_limit(bd, &w, &h);
3330          /* center x-direction */
3331          x1 = x1 + (pw - w) / 2;
3332          /* center y-direction */
3333          yy1 = yy1 + (ph - h) / 2;
3334
3335          switch (max & E_MAXIMIZE_DIRECTION)
3336            {
3337             case E_MAXIMIZE_BOTH:
3338               e_border_move_resize(bd, x1, yy1, w, h);
3339               break;
3340
3341             case E_MAXIMIZE_VERTICAL:
3342               e_border_move_resize(bd, bd->x, yy1, bd->w, h);
3343               break;
3344
3345             case E_MAXIMIZE_HORIZONTAL:
3346               e_border_move_resize(bd, x1, bd->y, w, bd->h);
3347               break;
3348
3349             case E_MAXIMIZE_LEFT:
3350               e_border_move_resize(bd, bd->zone->x, bd->zone->y, w / 2, h);
3351               break;
3352
3353             case E_MAXIMIZE_RIGHT:
3354               e_border_move_resize(bd, x1, bd->zone->y, w / 2, h);
3355               break;
3356            }
3357          break;
3358      }
3359 }
3360
3361 EAPI void
3362 e_border_maximize(E_Border  *bd,
3363                   E_Maximize max)
3364 {
3365    E_OBJECT_CHECK(bd);
3366    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3367
3368    if (!(max & E_MAXIMIZE_DIRECTION)) max |= E_MAXIMIZE_BOTH;
3369
3370    if ((bd->shaded) || (bd->shading)) return;
3371    ecore_x_window_shadow_tree_flush();
3372    if (bd->fullscreen)
3373      e_border_unfullscreen(bd);
3374    /* Only allow changes in vertical/ horizontal maximization */
3375    if (((bd->maximized & E_MAXIMIZE_DIRECTION) == (max & E_MAXIMIZE_DIRECTION)) ||
3376        ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
3377    if (bd->new_client)
3378      {
3379         bd->need_maximize = 1;
3380         bd->maximized &= ~E_MAXIMIZE_TYPE;
3381         bd->maximized |= max;
3382         return;
3383      }
3384
3385    bd->pre_res_change.valid = 0;
3386    if (!(bd->maximized & E_MAXIMIZE_HORIZONTAL))
3387      {
3388         /* Horizontal hasn't been set */
3389         bd->saved.x = bd->x - bd->zone->x;
3390         bd->saved.w = bd->w;
3391      }
3392    if (!(bd->maximized & E_MAXIMIZE_VERTICAL))
3393      {
3394         /* Vertical hasn't been set */
3395         bd->saved.y = bd->y - bd->zone->y;
3396         bd->saved.h = bd->h;
3397      }
3398
3399    bd->saved.zone = bd->zone->num;
3400    e_hints_window_size_set(bd);
3401
3402    e_border_raise(bd);
3403
3404    _e_border_maximize(bd, max);
3405
3406
3407    /* Remove previous type */
3408    bd->maximized &= ~E_MAXIMIZE_TYPE;
3409    /* Add new maximization. It must be added, so that VERTICAL + HORIZONTAL == BOTH */
3410    bd->maximized |= max;
3411
3412    e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
3413                                 bd->maximized & E_MAXIMIZE_VERTICAL);
3414    e_remember_update(bd);
3415 }
3416
3417 EAPI void
3418 e_border_unmaximize(E_Border  *bd,
3419                     E_Maximize max)
3420 {
3421    E_OBJECT_CHECK(bd);
3422    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3423    if (!(max & E_MAXIMIZE_DIRECTION))
3424      {
3425         CRI("BUG: Unmaximize call without direction!");
3426         return;
3427      }
3428
3429    if ((bd->shaded) || (bd->shading)) return;
3430    ecore_x_window_shadow_tree_flush();
3431    /* Remove directions not used */
3432    max &= (bd->maximized & E_MAXIMIZE_DIRECTION);
3433    /* Can only remove existing maximization directions */
3434    if (!max) return;
3435    if (bd->maximized & E_MAXIMIZE_TYPE)
3436      {
3437         bd->pre_res_change.valid = 0;
3438         bd->need_maximize = 0;
3439
3440         if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN)
3441           {
3442              if (bd->bg_object)
3443                {
3444                   edje_object_signal_emit(bd->bg_object, "e,action,unmaximize,fullscreen", "e");
3445                   _e_border_client_inset_calc(bd);
3446                }
3447
3448              bd->maximized = E_MAXIMIZE_NONE;
3449              _e_border_move_resize_internal(bd,
3450                                             bd->zone->x + bd->saved.x,
3451                                             bd->zone->y + bd->saved.y,
3452                                             bd->saved.w, bd->saved.h, 0, 1);
3453              bd->saved.x = bd->saved.y = bd->saved.w = bd->saved.h = 0;
3454              e_hints_window_size_unset(bd);
3455           }
3456         else
3457           {
3458              int w, h, x, y;
3459
3460              w = bd->w;
3461              h = bd->h;
3462              x = bd->x;
3463              y = bd->y;
3464
3465              if (max & E_MAXIMIZE_VERTICAL)
3466                {
3467                   /* Remove vertical */
3468                   h = bd->saved.h;
3469                   y = bd->saved.y + bd->zone->y;
3470                   bd->saved.h = bd->saved.y = 0;
3471                   bd->maximized &= ~E_MAXIMIZE_VERTICAL;
3472                   bd->maximized &= ~E_MAXIMIZE_LEFT;
3473                   bd->maximized &= ~E_MAXIMIZE_RIGHT;
3474                }
3475              if (max & E_MAXIMIZE_HORIZONTAL)
3476                {
3477                   /* Remove horizontal */
3478                   w = bd->saved.w;
3479                   x = bd->saved.x + bd->zone->x;
3480                   bd->saved.w = bd->saved.x = 0;
3481                   bd->maximized &= ~E_MAXIMIZE_HORIZONTAL;
3482                }
3483
3484              e_border_resize_limit(bd, &w, &h);
3485
3486              if (!(bd->maximized & E_MAXIMIZE_DIRECTION))
3487                {
3488                   bd->maximized = E_MAXIMIZE_NONE;
3489                   _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
3490                   e_hints_window_size_unset(bd);
3491                   edje_object_signal_emit(bd->bg_object, "e,action,unmaximize", "e");
3492                }
3493              else
3494                {
3495                   _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
3496                   e_hints_window_size_set(bd);
3497                }
3498           }
3499         e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
3500                                      bd->maximized & E_MAXIMIZE_VERTICAL);
3501      }
3502    e_remember_update(bd);
3503 }
3504
3505 EAPI void
3506 e_border_fullscreen(E_Border    *bd,
3507                     E_Fullscreen policy)
3508 {
3509    E_Event_Border_Fullscreen *ev;
3510
3511    E_OBJECT_CHECK(bd);
3512    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3513
3514    if ((bd->shaded) || (bd->shading)) return;
3515    ecore_x_window_shadow_tree_flush();
3516    if (bd->new_client)
3517      {
3518         bd->need_fullscreen = 1;
3519         return;
3520      }
3521    if (!bd->fullscreen)
3522      {
3523         bd->pre_res_change.valid = 0;
3524
3525         bd->saved.x = bd->x - bd->zone->x;
3526         bd->saved.y = bd->y - bd->zone->y;
3527         bd->saved.w = bd->client.w;
3528         bd->saved.h = bd->client.h;
3529         bd->saved.maximized = bd->maximized;
3530         bd->saved.zone = bd->zone->num;
3531
3532         if (bd->maximized)
3533           e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
3534         e_hints_window_size_set(bd);
3535
3536         bd->client_inset.l = 0;
3537         bd->client_inset.r = 0;
3538         bd->client_inset.t = 0;
3539         bd->client_inset.b = 0;
3540
3541         bd->desk->fullscreen_borders++;
3542
3543         /* e_zone_fullscreen_set(bd->zone, 1); */
3544         bd->saved.layer = bd->layer;
3545         if (!e_config->allow_above_fullscreen)
3546           e_border_layer_set(bd, 250);
3547
3548         if ((eina_list_count(bd->zone->container->zones) > 1) ||
3549             (policy == E_FULLSCREEN_RESIZE) || (!ecore_x_randr_query()))
3550           {
3551              e_border_move_resize(bd, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h);
3552           }
3553         else if (policy == E_FULLSCREEN_ZOOM)
3554           {
3555              Ecore_X_Randr_Screen_Size_MM *sizes;
3556              int num_sizes, i, best_size_index = 0;
3557
3558              ecore_x_randr_screen_primary_output_current_size_get(bd->zone->container->manager->root,
3559                                                                   &screen_size.width,
3560                                                                   &screen_size.height,
3561                                                                   NULL, NULL, NULL);
3562              sizes = ecore_x_randr_screen_primary_output_sizes_get(bd->zone->container->manager->root,
3563                                                                    &num_sizes);
3564              if (sizes)
3565                {
3566                   Ecore_X_Randr_Screen_Size best_size = { -1, -1 };
3567                   int best_dist = INT_MAX, dist;
3568
3569                   for (i = 0; i < num_sizes; i++)
3570                     {
3571                        if ((sizes[i].width > bd->w) && (sizes[i].height > bd->h))
3572                          {
3573                             dist = (sizes[i].width * sizes[i].height) - (bd->w * bd->h);
3574                             if (dist < best_dist)
3575                               {
3576                                  best_size.width = sizes[i].width;
3577                                  best_size.height = sizes[i].height;
3578                                  best_dist = dist;
3579                                  best_size_index = i;
3580                               }
3581                          }
3582                     }
3583                   if (((best_size.width != -1) && (best_size.height != -1)) &&
3584                       ((best_size.width != screen_size.width) ||
3585                        (best_size.height != screen_size.height)))
3586                     {
3587                        if (ecore_x_randr_screen_primary_output_size_set(bd->zone->container->manager->root,
3588                                                                         best_size_index))
3589                          screen_size_index = best_size_index;
3590                        e_border_move_resize(bd, 0, 0, best_size.width, best_size.height);
3591                     }
3592                   else
3593                     {
3594                        screen_size.width = -1;
3595                        screen_size.height = -1;
3596                        e_border_move_resize(bd, 0, 0, bd->zone->w, bd->zone->h);
3597                     }
3598                   free(sizes);
3599                }
3600              else
3601                e_border_move_resize(bd, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h);
3602           }
3603         bd->fullscreen = 1;
3604
3605         e_hints_window_fullscreen_set(bd, 1);
3606         e_hints_window_size_unset(bd);
3607         bd->client.border.changed = 1;
3608         bd->changed = 1;
3609      }
3610    bd->fullscreen_policy = policy;
3611
3612    ev = E_NEW(E_Event_Border_Fullscreen, 1);
3613    ev->border = bd;
3614    e_object_ref(E_OBJECT(bd));
3615    //   e_object_breadcrumb_add(E_OBJECT(bd), "border_fullscreen_event");
3616    ecore_event_add(E_EVENT_BORDER_FULLSCREEN, ev, _e_border_event_border_fullscreen_free, NULL);
3617
3618    e_remember_update(bd);
3619 }
3620
3621 EAPI void
3622 e_border_unfullscreen(E_Border *bd)
3623 {
3624    E_Event_Border_Unfullscreen *ev;
3625
3626    E_OBJECT_CHECK(bd);
3627    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3628    if ((bd->shaded) || (bd->shading)) return;
3629    ecore_x_window_shadow_tree_flush();
3630    if (bd->fullscreen)
3631      {
3632         bd->pre_res_change.valid = 0;
3633         bd->fullscreen = 0;
3634         bd->need_fullscreen = 0;
3635         bd->desk->fullscreen_borders--;
3636
3637         if ((screen_size.width != -1) && (screen_size.height != -1))
3638           {
3639              ecore_x_randr_screen_primary_output_size_set(bd->zone->container->manager->root,
3640                                                           screen_size_index);
3641              screen_size.width = -1;
3642              screen_size.height = -1;
3643           }
3644         e_border_move_resize(bd,
3645                              bd->saved.x + bd->zone->x,
3646                              bd->saved.y + bd->zone->y,
3647                              bd->saved.w, bd->saved.h);
3648
3649         if (bd->saved.maximized)
3650           e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) |
3651                             bd->saved.maximized);
3652
3653         e_border_layer_set(bd, bd->saved.layer);
3654
3655         e_hints_window_fullscreen_set(bd, 0);
3656         bd->client.border.changed = 1;
3657         bd->changed = 1;
3658      }
3659    bd->fullscreen_policy = 0;
3660
3661    ev = E_NEW(E_Event_Border_Unfullscreen, 1);
3662    ev->border = bd;
3663    e_object_ref(E_OBJECT(bd));
3664    //   e_object_breadcrumb_add(E_OBJECT(bd), "border_unfullscreen_event");
3665    ecore_event_add(E_EVENT_BORDER_UNFULLSCREEN, ev, _e_border_event_border_unfullscreen_free, NULL);
3666
3667    e_remember_update(bd);
3668 }
3669
3670 EAPI void
3671 e_border_iconify(E_Border *bd)
3672 {
3673    E_Event_Border_Iconify *ev;
3674    unsigned int iconic;
3675
3676    E_OBJECT_CHECK(bd);
3677    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3678    if (bd->shading) return;
3679    ecore_x_window_shadow_tree_flush();
3680    if (!bd->iconic)
3681      {
3682         bd->iconic = 1;
3683         e_border_hide(bd, 1);
3684         if (bd->fullscreen) bd->desk->fullscreen_borders--;
3685         edje_object_signal_emit(bd->bg_object, "e,action,iconify", "e");
3686      }
3687    iconic = 1;
3688    e_hints_window_iconic_set(bd);
3689    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
3690
3691    ev = E_NEW(E_Event_Border_Iconify, 1);
3692    ev->border = bd;
3693    e_object_ref(E_OBJECT(bd));
3694 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_iconify_event");
3695    ecore_event_add(E_EVENT_BORDER_ICONIFY, ev, _e_border_event_border_iconify_free, NULL);
3696
3697    if (e_config->transient.iconify)
3698      {
3699         Eina_List *l;
3700         E_Border *child;
3701         Eina_List *list = _e_border_sub_borders_new(bd);
3702
3703         EINA_LIST_FOREACH(list, l, child)
3704           {
3705              e_border_iconify(child);
3706           }
3707         eina_list_free(list);
3708      }
3709    e_remember_update(bd);
3710 }
3711
3712 #ifdef _F_DEICONIFY_APPROVE_
3713 static Eina_Bool
3714 _e_border_uniconify_timeout(void *data)
3715 {
3716    E_Border *bd;
3717    E_Border *child_bd;
3718
3719    bd = data;
3720
3721    if (!e_object_is_del(E_OBJECT(bd)))
3722      {
3723         ELB(ELBT_BD, "TIMEOUT UNICONIFY_APPROVE", bd->client.win);
3724         bd->client.e.state.deiconify_approve.render_done = 1;
3725         if (bd->client.e.state.deiconify_approve.req_list)
3726           {
3727              EINA_LIST_FREE(bd->client.e.state.deiconify_approve.req_list, child_bd)
3728                {
3729                   child_bd->client.e.state.deiconify_approve.render_done = 1;
3730                   child_bd->client.e.state.deiconify_approve.ancestor = NULL;
3731                }
3732           }
3733         bd->client.e.state.deiconify_approve.req_list = NULL;
3734         bd->client.e.state.deiconify_approve.wait_timer = NULL;
3735         e_border_uniconify(bd);
3736      }
3737
3738    return ECORE_CALLBACK_CANCEL;
3739 }
3740
3741 static void
3742 _e_border_deiconify_approve_send(E_Border *bd, E_Border *bd_ancestor)
3743 {
3744    if (!bd || !bd_ancestor) return;
3745
3746    if (e_config->deiconify_approve)
3747      {
3748         if (e_config->transient.iconify)
3749           {
3750              Eina_List *l;
3751              E_Border *child;
3752              Eina_List *list = _e_border_sub_borders_new(bd);
3753              EINA_LIST_FOREACH(list, l, child)
3754                {
3755 #ifdef _F_ZONE_WINDOW_ROTATION_
3756                   if ((e_config->wm_win_rotation) &&
3757                       ((child->client.e.state.rot.support) ||
3758                        (child->client.e.state.rot.app_set)))
3759                     {
3760                        ELB(ELBT_ROT, "CHECK_DEICONIFY CHILD", child->client.win);
3761                        _e_border_rotation_check(child);
3762                     }
3763 #endif
3764                   _e_border_deiconify_approve_send(child, bd_ancestor);
3765                   if (child->client.e.state.deiconify_approve.support)
3766                     {
3767                        ELBF(ELBT_BD, 0, child->client.win,
3768                             "SEND DEICONIFY_APPROVE. ancestor:%x", bd_ancestor->client.win);
3769
3770                        ecore_x_client_message32_send(child->client.win,
3771                                                      ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3772                                                      ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3773                                                      child->client.win, 0, 0, 0, 0);
3774                        child->client.e.state.deiconify_approve.ancestor = bd_ancestor;
3775                        bd_ancestor->client.e.state.deiconify_approve.req_list = eina_list_append(bd_ancestor->client.e.state.deiconify_approve.req_list, child);
3776                     }
3777                }
3778              eina_list_free(list);
3779           }
3780      }
3781 }
3782
3783 static void
3784 _e_border_deiconify_approve_send_all_transient(E_Border *bd)
3785 {
3786    E_Border *bd_ancestor;
3787    bd_ancestor = bd;
3788
3789    if (e_config->deiconify_approve)
3790      {
3791 #ifdef _F_ZONE_WINDOW_ROTATION_
3792         if ((e_config->wm_win_rotation) &&
3793             ((bd->client.e.state.rot.support) ||
3794              (bd->client.e.state.rot.app_set)))
3795           {
3796              ELB(ELBT_ROT, "CHECK_DEICONIFY", bd->client.win);
3797              _e_border_rotation_check(bd);
3798           }
3799 #endif
3800
3801         if (e_config->transient.iconify)
3802           {
3803              _e_border_deiconify_approve_send(bd, bd_ancestor);
3804           }
3805
3806         if (bd->client.e.state.deiconify_approve.support)
3807           {
3808              ELBF(ELBT_BD, 0, bd->client.win,
3809                   "SEND DEICONIFY_APPROVE.. ancestor:%x", bd_ancestor->client.win);
3810
3811              ecore_x_client_message32_send(bd->client.win,
3812                                            ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3813                                            ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3814                                            bd->client.win, 0, 0, 0, 0);
3815              bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
3816           }
3817      }
3818 }
3819 #endif
3820
3821 EAPI void
3822 e_border_uniconify(E_Border *bd)
3823 {
3824    E_Desk *desk;
3825    E_Event_Border_Uniconify *ev;
3826    unsigned int iconic;
3827
3828    E_OBJECT_CHECK(bd);
3829    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3830
3831 #ifdef _F_DEICONIFY_APPROVE_
3832    if (e_config->deiconify_approve)
3833      {
3834         if (bd->client.e.state.deiconify_approve.support)
3835           {
3836              if (bd->client.e.state.deiconify_approve.wait_timer)
3837                {
3838                   ELB(ELBT_BD, "DEICONIFY_APPROVE WAIT_TIMER is already running", bd->client.win);
3839                   return;
3840                }
3841              if (bd->client.e.state.deiconify_approve.render_done == 0)
3842                {
3843                   ELB(ELBT_BD, "DEICONIFY_APPROVE to all transient", bd->client.win);
3844                   _e_border_deiconify_approve_send_all_transient(bd);
3845                   return;
3846                }
3847           }
3848         bd->client.e.state.deiconify_approve.render_done = 0;
3849      }
3850 #endif
3851
3852 #if _F_ZONE_WINDOW_ROTATION_
3853    if (!bd->client.win)
3854      {
3855         ELB(ELBT_DFT, "ERR! obj is already deleted", bd->client.win);
3856         return;
3857      }
3858 #endif
3859
3860    if (bd->shading) return;
3861    ecore_x_window_shadow_tree_flush();
3862    e_border_show(bd);
3863    if (bd->iconic)
3864      {
3865         bd->iconic = 0;
3866         if (bd->fullscreen) bd->desk->fullscreen_borders++;
3867         desk = e_desk_current_get(bd->desk->zone);
3868 #ifdef _F_USE_EXTENDED_ICONIFY_
3869         if (e_manager_comp_evas_get(bd->zone->container->manager))
3870           {
3871              if (bd->await_hide_event > 0)
3872                bd->await_hide_event--;
3873           }
3874 #endif
3875         e_border_desk_set(bd, desk);
3876         e_border_raise(bd);
3877         edje_object_signal_emit(bd->bg_object, "e,action,uniconify", "e");
3878      }
3879    iconic = 0;
3880    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
3881
3882    ev = E_NEW(E_Event_Border_Uniconify, 1);
3883    ev->border = bd;
3884    e_object_ref(E_OBJECT(bd));
3885 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_uniconify_event");
3886    ecore_event_add(E_EVENT_BORDER_UNICONIFY, ev, _e_border_event_border_uniconify_free, NULL);
3887
3888    if (e_config->transient.iconify)
3889      {
3890         Eina_List *l;
3891         E_Border *child;
3892         Eina_List *list = _e_border_sub_borders_new(bd);
3893
3894         EINA_LIST_FOREACH(list, l, child)
3895           {
3896              e_border_uniconify(child);
3897           }
3898         eina_list_free(list);
3899      }
3900    e_remember_update(bd);
3901 }
3902
3903 EAPI void
3904 e_border_stick(E_Border *bd)
3905 {
3906    E_Event_Border_Stick *ev;
3907
3908    E_OBJECT_CHECK(bd);
3909    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3910    if (bd->sticky) return;
3911    bd->sticky = 1;
3912    e_hints_window_sticky_set(bd, 1);
3913    e_border_show(bd);
3914
3915    if (e_config->transient.desktop)
3916      {
3917         Eina_List *l;
3918         E_Border *child;
3919         Eina_List *list = _e_border_sub_borders_new(bd);
3920
3921         EINA_LIST_FOREACH(list, l, child)
3922           {
3923              child->sticky = 1;
3924              e_hints_window_sticky_set(child, 1);
3925              e_border_show(child);
3926           }
3927         eina_list_free(list);
3928      }
3929
3930    edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
3931    ev = E_NEW(E_Event_Border_Stick, 1);
3932    ev->border = bd;
3933    e_object_ref(E_OBJECT(bd));
3934 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_stick_event");
3935    ecore_event_add(E_EVENT_BORDER_STICK, ev, _e_border_event_border_stick_free, NULL);
3936    e_remember_update(bd);
3937 }
3938
3939 EAPI void
3940 e_border_unstick(E_Border *bd)
3941 {
3942    E_Event_Border_Unstick *ev;
3943
3944    E_OBJECT_CHECK(bd);
3945    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3946    /* Set the desk before we unstick the border */
3947    if (!bd->sticky) return;
3948    bd->sticky = 0;
3949    e_hints_window_sticky_set(bd, 0);
3950
3951    if (e_config->transient.desktop)
3952      {
3953         Eina_List *l;
3954         E_Border *child;
3955         Eina_List *list = _e_border_sub_borders_new(bd);
3956
3957         EINA_LIST_FOREACH(list, l, child)
3958           {
3959              child->sticky = 0;
3960              e_hints_window_sticky_set(child, 0);
3961           }
3962         eina_list_free(list);
3963      }
3964
3965    edje_object_signal_emit(bd->bg_object, "e,state,unsticky", "e");
3966    ev = E_NEW(E_Event_Border_Unstick, 1);
3967    ev->border = bd;
3968    e_object_ref(E_OBJECT(bd));
3969 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_unstick_event");
3970    ecore_event_add(E_EVENT_BORDER_UNSTICK, ev, _e_border_event_border_unstick_free, NULL);
3971
3972    e_border_desk_set(bd, e_desk_current_get(bd->zone));
3973    e_remember_update(bd);
3974 }
3975
3976 EAPI void
3977 e_border_pinned_set(E_Border *bd,
3978                     int       set)
3979 {
3980    int layer;
3981    int stacking;
3982
3983    if (bd)
3984      {
3985         bd->borderless = set;
3986         bd->user_skip_winlist = set;
3987         if (set)
3988           {
3989              layer = 50;
3990              stacking = E_STACKING_BELOW;
3991           }
3992         else
3993           {
3994              layer = 100;
3995              stacking = E_STACKING_NONE;
3996           }
3997
3998         e_border_layer_set(bd, layer);
3999         e_hints_window_stacking_set(bd, stacking);
4000
4001         bd->client.border.changed = 1;
4002         bd->changed = 1;
4003      }
4004 }
4005
4006 EAPI E_Border *
4007 e_border_find_by_client_window(Ecore_X_Window win)
4008 {
4009    E_Border *bd;
4010
4011    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4012    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4013        (bd->client.win == win))
4014      return bd;
4015    return NULL;
4016 }
4017
4018 EAPI E_Border *
4019 e_border_find_all_by_client_window(Ecore_X_Window win)
4020 {
4021    E_Border *bd;
4022
4023    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4024    if ((bd) && (bd->client.win == win))
4025      return bd;
4026    return NULL;
4027 }
4028
4029 EAPI E_Border *
4030 e_border_find_by_frame_window(Ecore_X_Window win)
4031 {
4032    E_Border *bd;
4033
4034    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4035    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4036        (bd->bg_win == win))
4037      return bd;
4038    return NULL;
4039 }
4040
4041 EAPI E_Border *
4042 e_border_find_by_window(Ecore_X_Window win)
4043 {
4044    E_Border *bd;
4045
4046    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4047    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4048        (bd->win == win))
4049      return bd;
4050    return NULL;
4051 }
4052
4053 EAPI E_Border *
4054 e_border_find_by_alarm(Ecore_X_Sync_Alarm al)
4055 {
4056    Eina_List *l;
4057    E_Border *bd;
4058
4059    EINA_LIST_FOREACH(borders, l, bd)
4060      {
4061         if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4062             (bd->client.netwm.sync.alarm == al))
4063           return bd;
4064      }
4065    return NULL;
4066 }
4067
4068 EAPI E_Border *
4069 e_border_focused_get(void)
4070 {
4071    return focused;
4072 }
4073
4074 static void
4075 _e_border_shape_input_rectangle_set(E_Border* bd)
4076 {
4077    if (!bd) return;
4078
4079    if ((bd->visible) && (bd->shaped_input))
4080      {
4081         Ecore_X_Rectangle rects[4];
4082         Ecore_X_Window twin, twin2;
4083         int x, y;
4084
4085         twin = ecore_x_window_override_new(bd->zone->container->scratch_win,
4086                                            0, 0, bd->w, bd->h);
4087         rects[0].x = 0;
4088         rects[0].y = 0;
4089         rects[0].width = bd->w;
4090         rects[0].height = bd->client_inset.t;
4091         rects[1].x = 0;
4092         rects[1].y = bd->client_inset.t;
4093         rects[1].width = bd->client_inset.l;
4094         rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
4095         rects[2].x = bd->w - bd->client_inset.r;
4096         rects[2].y = bd->client_inset.t;
4097         rects[2].width = bd->client_inset.r;
4098         rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
4099         rects[3].x = 0;
4100         rects[3].y = bd->h - bd->client_inset.b;
4101         rects[3].width = bd->w;
4102         rects[3].height = bd->client_inset.b;
4103         ecore_x_window_shape_input_rectangles_set(twin, rects, 4);
4104
4105         twin2 = ecore_x_window_override_new
4106            (bd->zone->container->scratch_win, 0, 0,
4107                bd->w - bd->client_inset.l - bd->client_inset.r,
4108                bd->h - bd->client_inset.t - bd->client_inset.b);
4109         x = 0;
4110         y = 0;
4111         if ((bd->shading) || (bd->shaded))
4112           {
4113              if (bd->shade.dir == E_DIRECTION_UP)
4114                 y = bd->h - bd->client_inset.t - bd->client_inset.b -
4115                 bd->client.h;
4116              else if (bd->shade.dir == E_DIRECTION_LEFT)
4117                 x = bd->w - bd->client_inset.l - bd->client_inset.r -
4118                 bd->client.w;
4119           }
4120         ecore_x_window_shape_input_window_set_xy(twin2, bd->client.win,
4121                                                  x, y);
4122         ecore_x_window_shape_input_rectangle_clip(twin2, 0, 0,
4123                                                   bd->w - bd->client_inset.l - bd->client_inset.r,
4124                                                   bd->h - bd->client_inset.t - bd->client_inset.b);
4125         ecore_x_window_shape_input_window_add_xy(twin, twin2,
4126                                                  bd->client_inset.l,
4127                                                  bd->client_inset.t);
4128         ecore_x_window_shape_input_window_set(bd->win, twin);
4129         ecore_x_window_free(twin2);
4130         ecore_x_window_free(twin);
4131      }
4132    else
4133      {
4134         if (bd->visible) // not shaped input
4135           {
4136              if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
4137                 ecore_x_composite_window_events_enable(bd->win);
4138              else
4139                 ecore_x_composite_window_events_disable(bd->win);
4140           }
4141         else
4142           {
4143              if (!e_manager_comp_evas_get(bd->zone->container->manager))
4144                 ecore_x_composite_window_events_enable(bd->win);
4145              else
4146                 ecore_x_composite_window_events_disable(bd->win);
4147           }
4148      }
4149 }
4150
4151 EAPI void
4152 e_border_idler_before(void)
4153 {
4154    Eina_List *ml, *cl;
4155    E_Manager *man;
4156    E_Container *con;
4157
4158    if (!borders)
4159      return;
4160
4161    EINA_LIST_FOREACH(e_manager_list(), ml, man)
4162      {
4163         EINA_LIST_FOREACH(man->containers, cl, con)
4164           {
4165              E_Border_List *bl;
4166              E_Border *bd;
4167
4168              // pass 1 - eval0. fetch properties on new or on change and
4169              // call hooks to decide what to do - maybe move/resize
4170              bl = e_container_border_list_last(con);
4171              while ((bd = e_container_border_list_prev(bl)))
4172                {
4173                   if (bd->changed) _e_border_eval0(bd);
4174                }
4175              e_container_border_list_free(bl);
4176
4177              // layout hook - this is where a hook gets to figure out what to
4178              // do if anything.
4179              _e_border_container_layout_hook(con);
4180
4181              // pass 2 - show windows needing show
4182              bl = e_container_border_list_last(con);
4183              while ((bd = e_container_border_list_prev(bl)))
4184                {
4185                   if ((bd->changes.visible) && (bd->visible) &&
4186                       (!bd->new_client) && (!bd->changes.pos) &&
4187                       (!bd->changes.size))
4188                     {
4189                        _e_border_show(bd);
4190                        bd->changes.visible = 0;
4191                     }
4192                }
4193              e_container_border_list_free(bl);
4194
4195              // pass 3 - hide windows needing hide and eval (main eval)
4196              bl = e_container_border_list_first(con);
4197              while ((bd = e_container_border_list_next(bl)))
4198                {
4199                   if (e_object_is_del(E_OBJECT(bd))) continue;
4200
4201                   if ((bd->changes.visible) && (!bd->visible))
4202                     {
4203                        _e_border_hide(bd);
4204                        bd->changes.visible = 0;
4205                     }
4206
4207                   if (bd->changed) _e_border_eval(bd);
4208
4209                   if ((bd->changes.visible) && (bd->visible))
4210                     {
4211                        _e_border_show(bd);
4212                        bd->changes.visible = 0;
4213                     }
4214                }
4215              e_container_border_list_free(bl);
4216           }
4217      }
4218
4219    if (focus_next)
4220      {
4221         E_Border *bd = NULL, *bd2;
4222
4223         EINA_LIST_FREE(focus_next, bd2)
4224           if ((!bd) && (bd2->visible)) bd = bd2;
4225
4226         if (!bd)
4227           {
4228              /* TODO revert focus when lost here ? */
4229              return;
4230           }
4231 #if 0
4232         if (bd == focused)
4233           {
4234              /* already focused. but anyway dont be so strict, this
4235                 fcks up illume setting focus on internal windows */
4236              return;
4237           }
4238 #endif
4239         
4240         focus_time = ecore_x_current_time_get();
4241
4242         focusing = bd;
4243
4244         if ((bd->client.icccm.take_focus) &&
4245             (bd->client.icccm.accepts_focus))
4246           {
4247              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
4248              /* TODO what if the client didn't take focus ? */
4249           }
4250         else if (!bd->client.icccm.accepts_focus)
4251           {
4252              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
4253           }
4254         else if (!bd->client.icccm.take_focus)
4255           {
4256              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
4257              /* e_border_focus_set(bd, 1, 0); */
4258           }
4259      }
4260
4261 #ifdef _F_ZONE_WINDOW_ROTATION_
4262    if ((e_config->wm_win_rotation) &&
4263        (rot.fetch))
4264      {
4265         Ecore_X_Event_Client_Message *msg = NULL;
4266         Ecore_X_Atom t = 0;
4267         EINA_LIST_FREE(rot.msgs, msg)
4268           {
4269              t = msg->message_type;
4270              if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)
4271                {
4272                   if ((rot.vkbd_ctrl_win) &&
4273                       ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) &&
4274                       (rot.vkbd))
4275                     {
4276                        ELB(ELBT_BD, "GET KBD_ON_PREPARE_DONE", rot.vkbd_ctrl_win);
4277                        if (rot.vkbd_show_prepare_timer)
4278                          _e_border_vkbd_show(rot.vkbd);
4279                        else
4280                          ELB(ELBT_BD, "GET KBD_ON_PREPARE_DONE but skip", rot.vkbd_ctrl_win);
4281                     }
4282                }
4283              else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE)
4284                {
4285                   if ((rot.vkbd_ctrl_win) &&
4286                       ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) &&
4287                       (rot.vkbd))
4288                     {
4289                        ELB(ELBT_BD, "GET KBD_OFF_PREPARE_DONE", rot.vkbd_ctrl_win);
4290                        if (rot.vkbd_hide_prepare_timer)
4291                          {
4292                             _e_border_vkbd_hide(rot.vkbd);
4293                             rot.vkbd_hide_prepare_timer = NULL;
4294                             e_object_unref(E_OBJECT(rot.vkbd));
4295                          }
4296                        else
4297                          ELB(ELBT_BD, "GET KBD_OFF_PREPARE_DONE but skip", rot.vkbd_ctrl_win);
4298                     }
4299                }
4300              else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)
4301                {
4302                   rot.vkbd_ctrl_win = msg->data.l[0];
4303                   ELB(ELBT_BD, "SET KBD_CONTROL_WIN", rot.vkbd_ctrl_win);
4304                }
4305              else if (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE)
4306                {
4307                   if ((rot.vkbd_ctrl_win) &&
4308                       (rot.vkbd_ctrl_win == (Ecore_X_Window)msg->data.l[0]))
4309                     {
4310                        ELB(ELBT_ROT, "GET ROT_PREPARE_DONE", rot.vkbd_ctrl_win);
4311                        E_Manager *m = e_manager_current_get();
4312                        E_Zone *zone = NULL;
4313                        if (m) zone = e_util_zone_current_get(m);
4314                        if ((zone) && (rot.wait_prepare_done))
4315                          {
4316                             if (!_e_border_rotation_start(zone, EINA_FALSE))
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           _e_border_rotation_start(e->zone, EINA_TRUE);
7935      }
7936    else
7937      {
7938         /* there is no border which supports window manager rotation */
7939         e_zone_rotation_update_cancel(e->zone);
7940      }
7941    return ECORE_CALLBACK_PASS_ON;
7942 }
7943
7944 static Eina_Bool
7945 _e_border_rotation_change_prepare_timeout(void *data)
7946 {
7947    E_Zone *zone = data;
7948    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
7949
7950    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE_PREPARE", 0);
7951
7952    if ((!rot.wait_prepare_done) ||
7953        (!zone) ||
7954        (!_e_border_rotation_start(zone, EINA_FALSE)))
7955      {
7956         if (rot.prepare_timer)
7957           ecore_timer_del(rot.prepare_timer);
7958         rot.prepare_timer = NULL;
7959         rot.wait_prepare_done = EINA_FALSE;
7960      }
7961    return ECORE_CALLBACK_CANCEL;
7962 }
7963
7964 static void
7965 _e_border_rotation_change_request(E_Zone *zone __UNUSED__)
7966 {
7967    Eina_List *l = NULL;
7968    E_Border_Rotation_Info *info = NULL;
7969
7970    if (!e_config->wm_win_rotation) return;
7971    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
7972    rot.prepare_timer = NULL;
7973    rot.wait_prepare_done = EINA_FALSE;
7974
7975    EINA_LIST_FOREACH(rot.list, l, info)
7976      {
7977         if (!info->bd) continue;
7978         if ((zone->rot.block_count) &&
7979             (info->bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_DEPENDENT)) continue;
7980
7981         _e_border_event_border_rotation_change_begin_send(info->bd);
7982
7983         ELBF(ELBT_ROT, 1, info->bd->client.win,
7984              "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
7985              info->ang, info->win_resize, info->w, info->h);
7986
7987         ecore_x_e_window_rotation_change_prepare_send
7988           (info->bd->client.win, info->ang,
7989           info->win_resize, info->w, info->h);
7990
7991         if (!info->bd->client.e.state.rot.pending_change_request)
7992           {
7993              ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
7994              ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
7995                                                            info->ang);
7996           }
7997      }
7998
7999    if (rot.done_timer)
8000      ecore_timer_del(rot.done_timer);
8001    rot.done_timer = ecore_timer_add(4.0f,
8002                                     _e_border_rotation_change_done_timeout,
8003                                     NULL);
8004 }
8005
8006 EAPI void
8007 e_border_rotation_list_clear(E_Zone *zone, Eina_Bool send_request)
8008 {
8009    Eina_List *l = NULL;
8010    E_Border_Rotation_Info *info = NULL;
8011
8012    if (send_request) _e_border_rotation_change_request(zone);
8013    else
8014      {
8015         EINA_LIST_FREE(rot.list, info)
8016            E_FREE(info);
8017         rot.list = NULL;
8018      }
8019 }
8020
8021 static void
8022 _e_border_rotation_list_remove(E_Border *bd)
8023 {
8024    Eina_List *l = NULL;
8025    E_Border_Rotation_Info *info = NULL;
8026    E_Event_Border_Rotation_Change_End *ev = NULL;
8027    if (!e_config->wm_win_rotation) return;
8028
8029    EINA_LIST_FOREACH(rot.list, l, info)
8030      {
8031         if (info->bd == bd)
8032           {
8033              rot.list = eina_list_remove(rot.list, info);
8034              E_FREE(info);
8035           }
8036      }
8037
8038    if (bd->client.e.state.rot.wait_for_done)
8039      {
8040         bd->client.e.state.rot.wait_for_done = 0;
8041
8042         /* if we make the border event in the _e_border_free function,
8043          * then we may meet a crash problem, only work this at least e_border_hide.
8044          */
8045         if (!e_object_is_del(E_OBJECT(bd)))
8046           {
8047              ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
8048              if (ev)
8049                {
8050                   ev->border = bd;
8051                   e_object_ref(E_OBJECT(bd));
8052                   ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_END,
8053                                   ev,
8054                                   _e_border_event_border_rotation_change_end_free,
8055                                   NULL);
8056                }
8057           }
8058         if (eina_list_count(rot.list) == 0)
8059           {
8060              _e_border_rotation_change_done();
8061           }
8062      }
8063 }
8064
8065 static Eina_Bool
8066 _e_border_rotation_change_done_timeout(void *data __UNUSED__)
8067 {
8068    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8069    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE", 0);
8070    _e_border_rotation_change_done();
8071    return ECORE_CALLBACK_CANCEL;
8072 }
8073
8074 static void
8075 _e_border_rotation_change_done(void)
8076 {
8077    E_Manager *m = NULL;
8078    E_Border_Rotation_Info *info = NULL;
8079
8080    if (!e_config->wm_win_rotation) return;
8081
8082    if (rot.prepare_timer)
8083      ecore_timer_del(rot.prepare_timer);
8084    rot.prepare_timer = NULL;
8085
8086    rot.wait_prepare_done = EINA_FALSE;
8087
8088    if (rot.done_timer)
8089      ecore_timer_del(rot.done_timer);
8090    rot.done_timer = NULL;
8091
8092    EINA_LIST_FREE(rot.list, info)
8093      {
8094         if (info->bd)
8095           {
8096              info->bd->client.e.state.rot.wait_for_done = 0;
8097              ELB(ELBT_ROT, "TIMEOUT ROT_DONE", info->bd->client.win);
8098           }
8099         E_FREE(info);
8100      }
8101
8102    rot.list = NULL;
8103
8104    m = e_manager_current_get();
8105    e_manager_comp_screen_unlock(m);
8106    e_zone_rotation_update_done(e_util_zone_current_get(m));
8107 }
8108
8109 static int
8110 _prev_angle_get(Ecore_X_Window win)
8111 {
8112    int ret, count = 0, ang = -1;
8113    unsigned char* data = NULL;
8114
8115    ret = ecore_x_window_prop_property_get
8116       (win, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
8117       ECORE_X_ATOM_CARDINAL, 32, &data, &count);
8118
8119    if ((ret) && (data) && (count))
8120      ang = ((int *)data)[0];
8121    if (data) free(data);
8122    return ang;
8123 }
8124
8125 /* get proper rotation value using preferred rotation and list of available rotations */
8126 static int
8127 _e_border_rotation_get(E_Border *bd,
8128                        int       base_ang)
8129 {
8130    int ang = -1;
8131    int current_ang = bd->client.e.state.rot.curr;
8132    unsigned int i;
8133    Eina_Bool found = EINA_FALSE;
8134    Eina_Bool found_curr_ang = EINA_FALSE;
8135
8136    if (!e_config->wm_win_rotation) return ang;
8137    if (!bd->client.e.state.rot.app_set) return ang;
8138
8139    if (bd->client.e.state.rot.preferred_rot != -1)
8140      {
8141         ang = bd->client.e.state.rot.preferred_rot;
8142         ELBF(ELBT_ROT, 0, bd->client.win, "ang:%d base_ang:%d", ang, base_ang);
8143      }
8144    else if ((bd->client.e.state.rot.available_rots) &&
8145             (bd->client.e.state.rot.count))
8146      {
8147         for (i = 0; i < bd->client.e.state.rot.count; i++)
8148           {
8149              if (bd->client.e.state.rot.available_rots[i] == base_ang)
8150                {
8151                   ang = base_ang;
8152                   found = EINA_TRUE;
8153                   break;
8154                }
8155              if (bd->client.e.state.rot.available_rots[i] == current_ang)
8156                found_curr_ang = EINA_TRUE;
8157           }
8158
8159         /* do nothing. this window wants to maintain current state.
8160          * for example, window's available_rots: 0, 90, 270,
8161          * current zone rotation request: 180. the WM does nothing
8162          * for this window.
8163          */
8164         if (!found)
8165           {
8166              if ((bd->client.e.state.rot.curr != -1) && (found_curr_ang))
8167                ang = bd->client.e.state.rot.curr;
8168              else
8169                ang = bd->client.e.state.rot.available_rots[0];
8170           }
8171      }
8172    else
8173      {
8174         /* In this case, border doesn't have a list of
8175          * available rotations, thus WM should request
8176          * rotation with '0' degree to the application.
8177          */
8178         ang = 0;
8179      }
8180
8181    return ang;
8182 }
8183
8184 #define REGION_EQUAL_TO_ZONE(a, z) \
8185    ((((a)->x) == ((z)->x)) &&      \
8186     (((a)->y) == ((z)->y)) &&      \
8187     (((a)->w) == ((z)->w)) &&      \
8188     (((a)->h) == ((z)->h)))
8189
8190 static Eina_Bool
8191 _e_border_rotation_check(E_Border *bd)
8192 {
8193    E_Zone *zone = bd->zone;
8194    Eina_List *nl = NULL;
8195    int x, y, w, h, ang = 0;
8196    int _ang = 0;
8197    Eina_Bool resize = EINA_TRUE;
8198    Eina_Bool hint = EINA_FALSE;
8199    Eina_Bool move = EINA_TRUE;
8200
8201    if (!e_config->wm_win_rotation) return EINA_FALSE;
8202
8203    ELB(ELBT_ROT, "CHECK ROT", bd->client.win);
8204
8205    ang = zone->rot.curr;
8206
8207    if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
8208      {
8209         ELBF(ELBT_ROT, 1, bd->client.win,
8210              "%s->parent:0x%08x (support:%d app_set:%d ang:%d)",
8211              (rot.vkbd == bd) ? "vkbd" : "prediction",
8212              bd->parent ? bd->parent->client.win : 0,
8213              bd->parent ? bd->parent->client.e.state.rot.support : -1,
8214              bd->parent ? bd->parent->client.e.state.rot.app_set : -1,
8215              bd->parent ? bd->parent->client.e.state.rot.curr : -1);
8216
8217         if (bd->parent)
8218           {
8219              ang = bd->parent->client.e.state.rot.curr;
8220              if ((!bd->parent->client.e.state.rot.support) &&
8221                  (!bd->parent->client.e.state.rot.app_set))
8222                {
8223                   ang = 0;
8224                }
8225           }
8226      }
8227
8228    if ((!bd->client.e.state.rot.app_set) &&
8229        (!bd->client.e.state.rot.support))
8230      {
8231         /* hack for magnifier and keyboard popup */
8232         if ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER) ||
8233             (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP))
8234           {
8235              ELB(ELBT_BD, "MAG", bd->client.win);
8236              ang = 0;
8237              if ((rot.vkbd) && (rot.vkbd->visible))
8238                ang = rot.vkbd->client.e.state.rot.curr;
8239              hint = _e_border_rotation_geom_get(bd, zone, ang, &x, &y, &w, &h, &move);
8240              if (hint)
8241                {
8242                   ELBF(ELBT_ROT, 1, bd->client.win, "MAG %d,%d %dx%d m:%d", x, y, w, h, move);
8243                   _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
8244                }
8245              return EINA_FALSE;
8246           }
8247      }
8248
8249    if (bd->client.e.state.rot.app_set)
8250      {
8251         /* utility type window should be rotated according to
8252          * rotation of the transient_for window.
8253          */
8254         if ((bd->parent) &&
8255             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
8256           {
8257              ang = bd->parent->client.e.state.rot.curr;
8258              if ((!bd->parent->client.e.state.rot.support) &&
8259                  (!bd->parent->client.e.state.rot.app_set))
8260                {
8261                   /* if transient_for window doesn't support rotation feature,
8262                    * then this window should't be rotated.
8263                    * TODO: need to check whether window supports '0' degree or not.
8264                    */
8265                   ang = 0;
8266                   ELBF(ELBT_ROT, 0, bd->client.win,
8267                        "GET ROT ang:%d Transient_For:0x%08x Not support rot",
8268                        ang, bd->parent->client.win);
8269                }
8270              else
8271                {
8272                   ang = _e_border_rotation_get(bd->parent, ang);
8273                   ELBF(ELBT_ROT, 0, bd->client.win,
8274                        "GET ROT ang:%d Transient_For:0x%08x",
8275                        ang, bd->parent->client.win);
8276                }
8277           }
8278         else
8279           {
8280              ang = _e_border_rotation_get(bd, ang);
8281              ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d",
8282                   ang, bd->parent ? bd->parent->client.win : 0,
8283                   bd->client.netwm.type);
8284           }
8285      }
8286
8287    hint = _e_border_rotation_geom_get(bd, zone, ang, &x, &y, &w, &h, &move);
8288    if (hint)
8289      {
8290         _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
8291         ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
8292              bd->client.icccm.name, x, y, w, h);
8293      }
8294
8295    /* need to check previous rotation angle, this may be because
8296     * the window was unmapped with non-0 rotation degree.
8297     * and now, the window wants to show on the 0 degree zone,
8298     * thus the wm should request to rotate the window to 0 degree.
8299     */
8300    if (!bd->visible)
8301      {
8302         _ang = _prev_angle_get(bd->client.win);
8303         if (_ang != -1)
8304           bd->client.e.state.rot.curr = _ang;
8305         ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang);
8306      }
8307
8308    if (bd->client.e.state.rot.curr != ang)
8309      {
8310         if ((rot.vkbd != bd) && (rot.vkbd_prediction != bd) &&
8311             /* check whether virtual keyboard is visible on the zone */
8312             (_e_border_rotation_zone_vkbd_check(bd->zone)) &&
8313             /* check whether virtual keyboard belongs to this border (transient_for) */
8314             (_e_border_rotation_vkbd_transient_for_check(bd)) &&
8315             /* check rotation of the virtual keyboard */
8316             (((rot.vkbd) && (rot.vkbd->client.e.state.rot.curr != ang)) ||
8317              ((rot.vkbd_prediction) && (rot.vkbd_prediction->client.e.state.rot.curr != ang))) &&
8318             (!rot.wait_prepare_done))
8319           {
8320              ELB(ELBT_ROT, "DO VKBD ROT", bd->client.win);
8321              e_manager_comp_screen_lock(e_manager_current_get());
8322
8323              if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8324              rot.prepare_timer = NULL;
8325
8326              if (rot.done_timer) ecore_timer_del(rot.done_timer);
8327              rot.done_timer = NULL;
8328
8329              ELB(ELBT_ROT, "send rot_change_prepare", rot.vkbd_ctrl_win);
8330              ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8331                                                            ang,
8332                                                            EINA_FALSE, 1, 1);
8333              rot.prepare_timer = ecore_timer_add(4.0f,
8334                                                  _e_border_rotation_change_prepare_timeout,
8335                                                  NULL);
8336              rot.wait_prepare_done = EINA_TRUE;
8337           }
8338
8339         bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8340         bd->client.e.state.rot.curr = ang;
8341         bd->client.e.state.rot.wait_for_done = 1;
8342         nl = eina_list_append(nl, bd);
8343
8344         e_border_rotation_list_add_change_req(zone, nl);
8345      }
8346    return EINA_TRUE;
8347 }
8348
8349 static Eina_Bool
8350 _e_border_rotation_zone_check(E_Zone *zone)
8351 {
8352    Eina_Bool wait = EINA_FALSE;
8353    E_Border_List *l = NULL;
8354    E_Border *bd = NULL;
8355
8356    if (!e_config->wm_win_rotation) return EINA_FALSE;
8357
8358    l = e_container_border_list_last(zone->container);
8359    if (!l) return EINA_FALSE;
8360    while ((bd = e_container_border_list_prev(l)))
8361      {
8362         if ((!bd) || (e_object_is_del(E_OBJECT(bd))) ||
8363             (!bd->visible) || (bd->zone != zone) ||
8364             (!E_INTERSECTS(zone->x, zone->y, zone->w, zone->h,
8365                            bd->x, bd->y, bd->w, bd->h))) continue;
8366
8367         if (((rot.vkbd) && (rot.vkbd == bd)) ||
8368             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)) ||
8369             ((REGION_EQUAL_TO_ZONE(bd, zone)) &&
8370              (bd->client.e.state.rot.preferred_rot != -1))) continue;
8371
8372         if (_e_border_rotation_border_check(bd, zone->rot.curr))
8373           {
8374              wait = EINA_TRUE;
8375              break;
8376           }
8377      }
8378    if (l) e_container_border_list_free(l);
8379
8380    return wait;
8381 }
8382
8383 // check if border is rotatable in ang.
8384 static Eina_Bool
8385 _e_border_rotation_border_check(E_Border *bd, int ang)
8386 {
8387    Eina_Bool wait = EINA_FALSE;
8388
8389    if (!bd) return wait;
8390
8391    if (((bd->client.e.state.rot.support) || (bd->client.e.state.rot.app_set)) &&
8392        /* basically WM allows only fullscreen window to rotate */
8393        ((REGION_EQUAL_TO_ZONE(bd, bd->zone)) ||
8394         /* we don't like this kind of code.
8395          * it means that the WM also allows non-fullscreen window to rotate if it sets geom hint.
8396          * such as large editable window.
8397          */
8398         ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE) && (bd->client.e.state.rot.geom_hint)) ||
8399         /* and floating mode window is also rotatable */
8400         (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) &&
8401        (bd->client.e.state.rot.preferred_rot == -1))
8402      {
8403         unsigned int i;
8404
8405         if (bd->client.e.state.rot.app_set)
8406           {
8407              if (bd->client.e.state.rot.available_rots &&
8408                  bd->client.e.state.rot.count)
8409                {
8410                   Eina_Bool found = EINA_FALSE;
8411                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8412                     {
8413                        if (bd->client.e.state.rot.available_rots[i] == ang)
8414                          {
8415                             found = EINA_TRUE;
8416                          }
8417                     }
8418                   if ((found) && (ang != bd->client.e.state.rot.curr))
8419                     {
8420                        wait = EINA_TRUE;
8421                     }
8422                   else
8423                     {
8424                        ELB(ELBT_ROT, "ROT CANCEL for preferred rot", bd->client.win);
8425                        wait = EINA_FALSE;
8426                     }
8427                }
8428           }
8429         else
8430           {
8431              ELB(ELBT_ROT, "DO ROT", 0);
8432              wait = EINA_TRUE;
8433           }
8434      }
8435
8436    return wait;
8437 }
8438
8439 /* check whether virtual keyboard is visible on the zone */
8440 static Eina_Bool
8441 _e_border_rotation_zone_vkbd_check(E_Zone *zone)
8442 {
8443    if (!e_config->wm_win_rotation) return EINA_FALSE;
8444
8445    if ((rot.vkbd_ctrl_win) &&
8446        (rot.vkbd) &&
8447        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8448        (rot.vkbd->visible) &&
8449        (rot.vkbd->zone == zone) &&
8450        (E_INTERSECTS(zone->x, zone->y,
8451                      zone->w, zone->h,
8452                      rot.vkbd->x, rot.vkbd->y,
8453                      rot.vkbd->w, rot.vkbd->h)))
8454      {
8455         return EINA_TRUE;
8456      }
8457    return EINA_FALSE;
8458 }
8459
8460 /* check whether border is parent of the virtual keyboard */
8461 static Eina_Bool
8462 _e_border_rotation_vkbd_transient_for_check(E_Border *bd)
8463 {
8464    if (!e_config->wm_win_rotation) return EINA_FALSE;
8465
8466    if (rot.vkbd_ctrl_win)
8467      {
8468         if ((rot.vkbd) && (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8469             (rot.vkbd != bd))
8470           {
8471              if (rot.vkbd->parent == bd)
8472                return EINA_TRUE;
8473           }
8474
8475         if ((rot.vkbd_prediction) && (!e_object_is_del(E_OBJECT(rot.vkbd_prediction))) &&
8476             (rot.vkbd_prediction != bd))
8477           {
8478              if (rot.vkbd_prediction == bd)
8479                return EINA_TRUE;
8480           }
8481      }
8482
8483    return EINA_FALSE;
8484 }
8485
8486 // check if bd's parent is rotatable.
8487 static Eina_Bool
8488 _e_border_rotation_transient_for_check(E_Border *bd, int ang)
8489 {
8490    Eina_Bool ret = EINA_FALSE;
8491
8492    if (!e_config->wm_win_rotation) return EINA_FALSE;
8493    if (!bd) return EINA_FALSE;
8494
8495    if (!bd->parent) ret = EINA_TRUE;
8496    else
8497      {
8498         if (_e_border_rotation_border_check(bd->parent, ang))
8499           ret = EINA_TRUE;
8500      }
8501
8502    return ret;
8503 }
8504
8505 EAPI Eina_Bool
8506 e_border_rotation_list_add_change_req(E_Zone *zone, Eina_List *list)
8507 {
8508    Eina_List *l;
8509    E_Border *bd;
8510    Eina_Bool ret = EINA_FALSE;
8511
8512    if (e_border_rotation_list_add(list))
8513      {
8514         EINA_LIST_FOREACH(list, l, bd)
8515            _e_border_hook_call(E_BORDER_HOOK_ROTATION_LIST_ADD, bd);
8516         _e_border_rotation_change_request(zone);
8517         ret = EINA_TRUE;
8518      }
8519
8520    return ret;
8521 }
8522
8523 EAPI Eina_Bool
8524 e_border_rotation_list_add(Eina_List *list)
8525 {
8526    Eina_List *l;
8527    E_Border *bd = NULL;
8528    E_Border_Rotation_Info *info = NULL;
8529    int x=0, y=0, w=0, h=0;
8530
8531    if (!list) return EINA_FALSE;
8532    EINA_LIST_FOREACH(list, l, bd)
8533      {
8534         info = E_NEW(E_Border_Rotation_Info, 1);
8535         if (!info) continue;
8536
8537         info->bd = bd;
8538         info->ang = bd->client.e.state.rot.curr;
8539         info->win_resize = _e_border_rotation_pre_resize(bd, &x, &y, &w, &h);
8540         info->x = x; info->y = y;
8541         info->w = w; info->h = h;
8542         if (info->win_resize) bd->client.e.state.rot.pending_change_request = 1;
8543         rot.list = eina_list_append(rot.list, info);
8544      }
8545
8546    return EINA_TRUE;
8547 }
8548
8549 #define SIZE_EQUAL_TO_ZONE(a, z) \
8550    ((((a)->w) == ((z)->w)) &&    \
8551     (((a)->h) == ((z)->h)))
8552 static Eina_Bool
8553 _e_border_rotation_pre_resize(E_Border *bd, int *x, int *y, int *w, int *h)
8554 {
8555    E_Zone *zone = bd->zone;
8556    int ang = bd->client.e.state.rot.curr;
8557    int diff = ang - bd->client.e.state.rot.prev;
8558    int _x, _y, _w, _h;
8559    Eina_Bool move = EINA_FALSE;
8560    Eina_Bool hint = EINA_FALSE;
8561    Eina_Bool resize = EINA_FALSE;
8562
8563    if (x) *x = bd->x;
8564    if (y) *y = bd->y;
8565    if (w) *w = bd->w;
8566    if (h) *h = bd->h;
8567
8568    if (SIZE_EQUAL_TO_ZONE(bd, zone)) return resize;
8569
8570    ELB(ELBT_ROT, "SIZE DIFF WITH ZONE", 0);
8571    ELBF(ELBT_ROT, 0, bd->client.win, "ORIGIN_SIZE name:%s (%d,%d) %dx%d",
8572         bd->client.icccm.name, bd->x, bd->y, bd->w, bd->h);
8573
8574    hint = _e_border_rotation_geom_get(bd, bd->zone, ang,
8575                                       &_x, &_y, &_w, &_h, &move);
8576    if (hint)
8577      {
8578         _e_border_move_resize_internal(bd, _x, _y, _w, _h, EINA_TRUE, move);
8579         resize = EINA_TRUE;
8580         ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
8581              bd->client.icccm.name, _x, _y, _w, _h);
8582      }
8583    else
8584      {
8585         _x = bd->x; _y = bd->y;
8586         _w = bd->w; _h = bd->h;
8587
8588         if ((diff != 180) && (diff != -180))
8589           {
8590              if (w != h)
8591                {
8592                   _w = bd->h;
8593                   _h = bd->w;
8594                   resize = EINA_TRUE;
8595
8596                   _e_border_move_resize_internal(bd, _x, _y, _w, _h,
8597                                                  EINA_TRUE, EINA_TRUE);
8598                   ELBF(ELBT_ROT, 0, bd->client.win, "MANUAL_RESIZE name:%s (%d,%d) %dx%d",
8599                        bd->client.icccm.name, _x, _y, _w, _h);
8600
8601                }
8602           }
8603      }
8604
8605    if (resize)
8606      {
8607         if (x) *x = _x;
8608         if (y) *y = _y;
8609         if (w) *w = _w;
8610         if (h) *h = _h;
8611      }
8612
8613    return resize;
8614 }
8615
8616 static Eina_Bool
8617 _e_border_rotation_start(E_Zone *zone, Eina_Bool without_vkbd)
8618 {
8619    Eina_Bool wait = EINA_FALSE;
8620    E_Border_List *l = NULL;
8621    Eina_List *nl = NULL;
8622    E_Border *bd = NULL;
8623    E_Border_Rotation_Info *info = NULL;
8624
8625    if (!e_config->wm_win_rotation) return EINA_FALSE;
8626
8627    l = e_container_border_list_last(zone->container);
8628    if (!l) return EINA_FALSE;
8629    while ((bd = e_container_border_list_prev(l)))
8630      {
8631         if ((!bd) || (e_object_is_del(E_OBJECT(bd)))) continue;
8632
8633         if ((without_vkbd) &&
8634             (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE))
8635           {
8636              continue;
8637           }
8638
8639         if ((bd->visible) &&
8640             ((bd->client.e.state.rot.support) || (bd->client.e.state.rot.app_set)) &&
8641             (bd->zone == zone) &&
8642             (E_INTERSECTS(zone->x, zone->y, zone->w, zone->h,
8643                           bd->x, bd->y, bd->w, bd->h)))
8644           {
8645              if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue;
8646
8647              // check if this window is available to be rotate.
8648              if ((bd->client.e.state.rot.app_set) &&
8649                  (bd->client.e.state.rot.preferred_rot != -1)) continue;
8650
8651              /* check list of available rotations */
8652              int ang = zone->rot.curr;
8653              if (bd->client.e.state.rot.app_set)
8654                {
8655                   ang = _e_border_rotation_get(bd, ang);
8656                   ELBF(ELBT_ROT, 0, bd->client.win, "returned ang:%d", ang);
8657                }
8658
8659              /* skip same angle */
8660              if (bd->client.e.state.rot.curr == ang)
8661                {
8662                   /* FIXME: hack for rotating vkbd:
8663                    * even if angle of zone is not changed,
8664                    * if preferred_rot of parent is set with specific angle, vkbd has to rotate, too.
8665                    * all of other transient window like this case.
8666                    */
8667                   if ((bd->parent) &&
8668                       (bd->parent->client.e.state.rot.preferred_rot != -1))
8669                     ang = bd->parent->client.e.state.rot.preferred_rot;
8670                   if (bd->client.e.state.rot.curr == ang)
8671                     {
8672                        ELBF(ELBT_ROT, 0, bd->client.win, "SKIP ang:%d", ang);
8673                        continue;
8674                     }
8675                   ELBF(ELBT_ROT, 0, bd->client.win, "rotate by parent ang:%d", ang);
8676                }
8677              else
8678                {
8679                   ELBF(ELBT_ROT, 0, bd->client.win, "ADD ROT_LIST curr:%d != ang:%d",
8680                        bd->client.e.state.rot.curr, ang);
8681                }
8682
8683              bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8684              bd->client.e.state.rot.curr = ang;
8685              bd->client.e.state.rot.wait_for_done = 1;
8686              nl = eina_list_append(nl, bd);
8687
8688              /* check whether rotation is available for sub borders such as prediction and magnifier */
8689              Eina_List *ll;
8690              E_Border *_child;
8691              Eina_List *_list = _e_border_sub_borders_new(bd);
8692              EINA_LIST_FOREACH(_list, ll, _child)
8693                {
8694                   if ((_child->client.e.state.rot.support) ||
8695                       (_child->client.e.state.rot.app_set))
8696                     _e_border_rotation_check(_child);
8697                }
8698              eina_list_free(_list);
8699
8700              wait = EINA_TRUE;
8701           }
8702      }
8703
8704    if (l) e_container_border_list_free(l);
8705
8706    wait = e_border_rotation_list_add_change_req(zone, nl);
8707    eina_list_free(nl);
8708
8709    return wait;
8710 }
8711
8712 static Eina_Bool
8713 _e_border_cb_window_configure(void *data    __UNUSED__,
8714                               int   ev_type __UNUSED__,
8715                               void         *ev)
8716 {
8717    Ecore_X_Event_Window_Configure *e = ev;
8718    if (!e) return ECORE_CALLBACK_PASS_ON;
8719    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8720
8721    E_Border *bd = e_border_find_by_client_window(e->win);
8722    if (!bd) return ECORE_CALLBACK_PASS_ON;
8723
8724    if (bd->client.e.state.rot.pending_change_request)
8725      {
8726         if ((e->w == bd->w) && (e->h == bd->h))
8727           {
8728              ELBF(ELBT_ROT, 0, bd->client.win,
8729                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
8730                   bd->client.e.state.rot.curr,
8731                   bd->w, bd->h);
8732
8733              bd->client.e.state.rot.pending_change_request = 0;
8734
8735              ecore_x_e_window_rotation_change_request_send(bd->client.win,
8736                                                            bd->client.e.state.rot.curr);
8737           }
8738      }
8739    return ECORE_CALLBACK_PASS_ON;
8740 }
8741
8742 static Eina_Bool
8743 _e_border_rotation_geom_get(E_Border  *bd,
8744                             E_Zone    *zone,
8745                             int        ang,
8746                             int       *x,
8747                             int       *y,
8748                             int       *w,
8749                             int       *h,
8750                             Eina_Bool *move)
8751 {
8752    if (!e_config->wm_win_rotation) return EINA_FALSE;
8753
8754    Eina_Bool res = EINA_FALSE;
8755    Eina_Bool _move = EINA_TRUE;
8756    int _x = bd->x;
8757    int _y = bd->y;
8758    int _w = bd->w;
8759    int _h = bd->h;
8760
8761    if (x) *x = bd->x;
8762    if (y) *y = bd->y;
8763    if (w) *w = bd->w;
8764    if (h) *h = bd->h;
8765    if (move) *move = EINA_TRUE;
8766
8767    if (bd->client.e.state.rot.geom_hint)
8768      {
8769         switch (ang)
8770           {
8771            case   0:
8772               _w = bd->client.e.state.rot.geom[0].w;
8773               _h = bd->client.e.state.rot.geom[0].h;
8774               if (_w == 0) _w = bd->w;
8775               if (_h == 0) _h = bd->h;
8776               _x = 0; _y = zone->h - _h;
8777               break;
8778            case  90:
8779               _w = bd->client.e.state.rot.geom[1].w;
8780               _h = bd->client.e.state.rot.geom[1].h;
8781               if (_w == 0) _w = bd->w;
8782               if (_h == 0) _h = bd->h;
8783               _x = zone->w - _w; _y = 0;
8784               break;
8785            case 180:
8786               _w = bd->client.e.state.rot.geom[2].w;
8787               _h = bd->client.e.state.rot.geom[2].h;
8788               if (_w == 0) _w = bd->w;
8789               if (_h == 0) _h = bd->h;
8790               _x = 0; _y = 0;
8791               break;
8792            case 270:
8793               _w = bd->client.e.state.rot.geom[3].w;
8794               _h = bd->client.e.state.rot.geom[3].h;
8795               if (_w == 0) _w = bd->w;
8796               if (_h == 0) _h = bd->h;
8797               _x = 0; _y = 0;
8798               break;
8799           }
8800
8801         if (x) *x = _x;
8802         if (y) *y = _y;
8803         if (w) *w = _w;
8804         if (h) *h = _h;
8805
8806         if (!((rot.vkbd) && (rot.vkbd == bd)))
8807           {
8808              if (x) *x = bd->x;
8809              if (y) *y = bd->y;
8810              if (move) *move = EINA_FALSE;
8811           }
8812
8813         res = EINA_TRUE;
8814      }
8815
8816    if (res)
8817      {
8818         _x = 0; _y = 0; _w = 0; _h = 0;
8819         if (x) _x = *x;
8820         if (y) _y = *y;
8821         if (w) _w = *w;
8822         if (h) _h = *h;
8823         if (move) _move = *move;
8824
8825         ELBF(ELBT_ROT, 1, bd->client.win,
8826              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
8827              ang, _x, _y, _w, _h, _move);
8828      }
8829
8830    return res;
8831 }
8832 #endif
8833
8834 static Eina_Bool
8835 _e_border_post_move_resize_job(void *data)
8836 {
8837    E_Border *bd;
8838
8839    bd = (E_Border *)data;
8840    if (bd->post_move)
8841      {
8842         E_Border *tmp;
8843         Eina_List *l;
8844
8845         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
8846           ecore_x_window_move(tmp->win,
8847                               bd->x +
8848                               bd->client_inset.l +
8849                               bd->fx.x +
8850                               tmp->client.e.state.video_position.x,
8851                               bd->y +
8852                               bd->client_inset.t +
8853                               bd->fx.y +
8854                               tmp->client.e.state.video_position.y);
8855      }
8856    if (bd->client.e.state.video)
8857      {
8858         E_Border *parent;
8859
8860         parent = bd->client.e.state.video_parent_border;
8861         ecore_x_window_move(bd->win,
8862                             parent->x +
8863                             parent->client_inset.l +
8864                             parent->fx.x +
8865                             bd->client.e.state.video_position.x,
8866                             parent->y +
8867                             parent->client_inset.t +
8868                             parent->fx.y +
8869                             bd->client.e.state.video_position.y);
8870      }
8871    else if ((bd->post_move) && (bd->post_resize))
8872      {
8873         ecore_x_window_move_resize(bd->win,
8874                                    bd->x + bd->fx.x,
8875                                    bd->y + bd->fx.y,
8876                                    bd->w, bd->h);
8877      }
8878    else if (bd->post_move)
8879      {
8880         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
8881      }
8882    else if (bd->post_resize)
8883      {
8884         ecore_x_window_resize(bd->win, bd->w, bd->h);
8885      }
8886
8887    if (bd->client.e.state.video)
8888      {
8889         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
8890                 bd->win,
8891                 bd->client.e.state.video_parent_border->x +
8892                 bd->client.e.state.video_parent_border->client_inset.l +
8893                 bd->client.e.state.video_parent_border->fx.x +
8894                 bd->client.e.state.video_position.x,
8895                 bd->client.e.state.video_parent_border->y +
8896                 bd->client.e.state.video_parent_border->client_inset.t +
8897                 bd->client.e.state.video_parent_border->fx.y +
8898                 bd->client.e.state.video_position.y,
8899                 bd->w, bd->h);
8900      }
8901
8902    if (bd->post_show)
8903      {
8904         if (bd->visible)
8905           {
8906              bd->post_job = NULL;
8907              _e_border_show(bd);
8908           }
8909      }
8910    bd->post_show = 0;
8911    bd->post_move = 0;
8912    bd->post_resize = 0;
8913    bd->post_job = NULL;
8914    return ECORE_CALLBACK_CANCEL;
8915 }
8916
8917 static void
8918 _e_border_container_layout_hook(E_Container *con)
8919 {
8920    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
8921 }
8922
8923 static void
8924 _e_border_eval0(E_Border *bd)
8925 {
8926    int change_urgent = 0;
8927    int rem_change = 0;
8928 #ifdef _F_USE_DESK_WINDOW_PROFILE_
8929    Eina_Bool need_desk_set = EINA_FALSE;
8930 #endif
8931 #ifdef _F_ZONE_WINDOW_ROTATION_
8932    Eina_Bool need_rotation_set = EINA_FALSE;
8933
8934    if ((e_config->wm_win_rotation) &&
8935        (bd->client.icccm.fetch.transient_for))
8936      {
8937         if (((rot.vkbd) && (rot.vkbd == bd)) ||
8938             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
8939           {
8940              need_rotation_set = EINA_TRUE;
8941              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
8942           }
8943      }
8944 #endif
8945
8946    if (e_object_is_del(E_OBJECT(bd)))
8947      {
8948         CRI("_e_border_eval(%p) with deleted border!\n", bd);
8949         bd->changed = 0;
8950         return;
8951      }
8952
8953    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
8954
8955    bd->changes.border = 0;
8956
8957    /* fetch any info queued to be fetched */
8958    if (bd->client.netwm.fetch.state)
8959      {
8960         e_hints_window_state_get(bd);
8961         bd->client.netwm.fetch.state = 0;
8962         rem_change = 1;
8963      }
8964    if (bd->client.icccm.fetch.client_leader)
8965      {
8966         /* TODO: What do to if the client leader isn't mapped yet? */
8967         E_Border *bd_leader = NULL;
8968
8969         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
8970         if (bd->client.icccm.client_leader)
8971           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
8972         if (bd->leader)
8973           {
8974              if (bd->leader != bd_leader)
8975                {
8976                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
8977                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
8978                   bd->leader = NULL;
8979                }
8980              else
8981                bd_leader = NULL;
8982           }
8983         /* If this border is the leader of the group, don't register itself */
8984         if ((bd_leader) && (bd_leader != bd))
8985           {
8986              bd_leader->group = eina_list_append(bd_leader->group, bd);
8987              bd->leader = bd_leader;
8988              /* Only set the window modal to the leader it there is no parent */
8989              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
8990                  ((!bd->parent) || (bd->parent->modal != bd)))
8991                {
8992                   bd->leader->modal = bd;
8993                   if (bd->leader->focused)
8994                     e_border_focus_set(bd, 1, 1);
8995                   else
8996                     {
8997                        Eina_List *l;
8998                        E_Border *child;
8999
9000                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9001                          {
9002                             if ((child != bd) && (child->focused))
9003                               e_border_focus_set(bd, 1, 1);
9004                          }
9005                     }
9006                }
9007           }
9008         bd->client.icccm.fetch.client_leader = 0;
9009         rem_change = 1;
9010      }
9011    if (bd->client.icccm.fetch.title)
9012      {
9013         char *title = ecore_x_icccm_title_get(bd->client.win);
9014         eina_stringshare_replace(&bd->client.icccm.title, title);
9015         if (title) free(title);
9016
9017         if (bd->bg_object)
9018           edje_object_part_text_set(bd->bg_object, "e.text.title",
9019                                     bd->client.icccm.title);
9020         bd->client.icccm.fetch.title = 0;
9021         rem_change = 1;
9022      }
9023    if (bd->client.netwm.fetch.name)
9024      {
9025         char *name;
9026         ecore_x_netwm_name_get(bd->client.win, &name);
9027         eina_stringshare_replace(&bd->client.netwm.name, name);
9028         if (name) free(name);
9029
9030         if (bd->bg_object)
9031           edje_object_part_text_set(bd->bg_object, "e.text.title",
9032                                     bd->client.netwm.name);
9033         bd->client.netwm.fetch.name = 0;
9034         rem_change = 1;
9035      }
9036    if (bd->client.icccm.fetch.name_class)
9037      {
9038         const char *pname, *pclass;
9039         char *nname, *nclass;
9040
9041         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
9042         pname = bd->client.icccm.name;
9043         pclass = bd->client.icccm.class;
9044         bd->client.icccm.name = eina_stringshare_add(nname);
9045         bd->client.icccm.class = eina_stringshare_add(nclass);
9046         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
9047           e_bindings_mapping_change_enable(EINA_FALSE);
9048 #ifdef _F_ZONE_WINDOW_ROTATION_
9049         if (e_config->wm_win_rotation)
9050           {
9051              if ((bd->client.icccm.name) && (bd->client.icccm.class))
9052                {
9053                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
9054                       (!strcmp(bd->client.icccm.class, "ISF")))
9055                     {
9056                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
9057                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
9058                        rot.vkbd = bd;
9059                     }
9060                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
9061                            (!strcmp(bd->client.icccm.class, "ISF")))
9062                     {
9063                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
9064                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
9065                        rot.vkbd_prediction = bd;
9066                     }
9067                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
9068                            (!strcmp(bd->client.icccm.class, "ISF")))
9069                     {
9070                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
9071                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
9072                     }
9073                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
9074                            (!strcmp(bd->client.icccm.class, "ISF")))
9075                     {
9076                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
9077                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
9078                     }
9079                }
9080           }
9081 #endif
9082         if (nname) free(nname);
9083         if (nclass) free(nclass);
9084
9085         if (!((bd->client.icccm.name == pname) &&
9086               (bd->client.icccm.class == pclass)))
9087           bd->changes.icon = 1;
9088
9089         if (pname) eina_stringshare_del(pname);
9090         if (pclass) eina_stringshare_del(pclass);
9091         bd->client.icccm.fetch.name_class = 0;
9092         bd->changes.icon = 1;
9093         rem_change = 1;
9094      }
9095    if (bd->client.icccm.fetch.state)
9096      {
9097         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
9098         bd->client.icccm.fetch.state = 0;
9099         rem_change = 1;
9100      }
9101    if (bd->client.e.fetch.state)
9102      {
9103         e_hints_window_e_state_get(bd);
9104         bd->client.e.fetch.state = 0;
9105         rem_change = 1;
9106      }
9107 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9108    if (bd->client.e.fetch.profile_list)
9109      {
9110         const char **profiles = NULL;
9111         const char *str;
9112         int num = 0, i;
9113
9114         if (bd->client.e.state.profile)
9115           eina_stringshare_del(bd->client.e.state.profile);
9116         EINA_LIST_FREE(bd->client.e.state.profiles, str)
9117           {
9118              if (str) eina_stringshare_del(str);
9119           }
9120         bd->client.e.state.profile = NULL;
9121         bd->client.e.state.profiles = NULL;
9122         bd->client.e.state.profile_list = 0;
9123
9124         if (ecore_x_e_window_profile_list_get(bd->client.win,
9125                                               &profiles, &num))
9126           {
9127              bd->client.e.state.profile_list = 1;
9128              for (i = 0; i < num; i++)
9129                {
9130                   str = eina_stringshare_add(profiles[i]);
9131                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
9132                }
9133
9134              /* We should set desk to contain given border after creating E_BORDER_ADD event.
9135               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
9136               */
9137              need_desk_set = EINA_TRUE;
9138           }
9139         else
9140           {
9141              if (strcmp(bd->desk->window_profile,
9142                         e_config->desktop_default_window_profile) != 0)
9143                {
9144                   ecore_x_e_window_profile_set(bd->client.win,
9145                                                bd->desk->window_profile);
9146                }
9147           }
9148
9149         if (profiles)
9150           {
9151              for (i = 0; i < num; i++)
9152                 if (profiles[i]) free(profiles[i]);
9153              free(profiles);
9154           }
9155
9156         bd->client.e.fetch.profile_list = 0;
9157      }
9158 #endif
9159 #ifdef _F_ZONE_WINDOW_ROTATION_
9160    if ((e_config->wm_win_rotation) &&
9161        (bd->client.e.fetch.rot.support))
9162      {
9163         int ret = 0;
9164         unsigned int support = 0;
9165
9166         ret = ecore_x_window_prop_card32_get
9167           (bd->client.win,
9168           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
9169           &support, 1);
9170
9171         bd->client.e.state.rot.support = 0;
9172         if ((ret == 1) && (support == 1))
9173           bd->client.e.state.rot.support = 1;
9174
9175         if (bd->client.e.state.rot.support)
9176           need_rotation_set = EINA_TRUE;
9177
9178         bd->client.e.fetch.rot.support = 0;
9179      }
9180    if ((e_config->wm_win_rotation) &&
9181        (bd->client.e.fetch.rot.geom_hint))
9182      {
9183         Eina_Rectangle r[4];
9184         int i, x, y, w, h;
9185         bd->client.e.state.rot.geom_hint = 0;
9186         for (i = 0; i < 4; i++)
9187           {
9188              r[i].x = bd->client.e.state.rot.geom[i].x;
9189              r[i].y = bd->client.e.state.rot.geom[i].y;
9190              r[i].w = bd->client.e.state.rot.geom[i].w;
9191              r[i].h = bd->client.e.state.rot.geom[i].h;
9192
9193              bd->client.e.state.rot.geom[i].x = 0;
9194              bd->client.e.state.rot.geom[i].y = 0;
9195              bd->client.e.state.rot.geom[i].w = 0;
9196              bd->client.e.state.rot.geom[i].h = 0;
9197           }
9198
9199         for (i = 0; i < 4; i++)
9200           {
9201              x = 0; y = 0; w = 0; h = 0;
9202              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
9203                {
9204                   bd->client.e.state.rot.geom_hint = 1;
9205                   bd->client.e.state.rot.geom[i].x = x;
9206                   bd->client.e.state.rot.geom[i].y = y;
9207                   bd->client.e.state.rot.geom[i].w = w;
9208                   bd->client.e.state.rot.geom[i].h = h;
9209
9210                   if (!((r[i].x == x) && (r[i].y == y) &&
9211                         (r[i].w == w) && (r[i].h == h)))
9212                     {
9213                        need_rotation_set = EINA_TRUE;
9214                     }
9215                }
9216           }
9217         bd->client.e.fetch.rot.geom_hint = 0;
9218      }
9219    if ((e_config->wm_win_rotation) &&
9220        (bd->client.e.fetch.rot.app_set))
9221      {
9222         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
9223         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
9224         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
9225
9226         if (_prev_app_set != bd->client.e.state.rot.app_set)
9227           need_rotation_set = EINA_TRUE;
9228
9229         bd->client.e.fetch.rot.app_set = 0;
9230      }
9231    if ((e_config->wm_win_rotation) &&
9232        (bd->client.e.fetch.rot.preferred_rot))
9233      {
9234         int r = 0, _prev_preferred_rot;
9235         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
9236         bd->client.e.state.rot.preferred_rot = -1;
9237         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
9238           {
9239              bd->client.e.state.rot.preferred_rot = r;
9240              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
9241           }
9242         else
9243           {
9244              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
9245           }
9246
9247         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
9248           need_rotation_set = EINA_TRUE;
9249
9250         bd->client.e.fetch.rot.preferred_rot = 0;
9251      }
9252    if ((e_config->wm_win_rotation) &&
9253        (bd->client.e.fetch.rot.available_rots))
9254      {
9255         Eina_Bool res, diff = EINA_FALSE;
9256         int *rots = NULL;
9257         unsigned int count = 0, i = 0;
9258         int _prev_rots[4] = { -1, };
9259
9260         if (bd->client.e.state.rot.available_rots)
9261           {
9262              memcpy(_prev_rots,
9263                     bd->client.e.state.rot.available_rots,
9264                     (sizeof(int) * bd->client.e.state.rot.count));
9265
9266              E_FREE(bd->client.e.state.rot.available_rots);
9267           }
9268
9269         bd->client.e.state.rot.count = 0;
9270
9271         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
9272                                                                 &rots, &count);
9273         if ((res) && (count > 0) && (rots))
9274           {
9275              bd->client.e.state.rot.available_rots = rots;
9276              bd->client.e.state.rot.count = count;
9277
9278              for (i = 0; i < count; i++)
9279                {
9280                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
9281                   if ((!diff) && (_prev_rots[i] != rots[i]))
9282                     {
9283                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
9284                             count, i, _prev_rots[i], rots[i]);
9285                        diff = EINA_TRUE;
9286                     }
9287                }
9288           }
9289         else
9290           {
9291              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9292              diff = EINA_TRUE;
9293           }
9294
9295         if (diff) need_rotation_set = EINA_TRUE;
9296         bd->client.e.fetch.rot.available_rots = 0;
9297      }
9298 #endif
9299    if (bd->client.netwm.fetch.type)
9300      {
9301         e_hints_window_type_get(bd);
9302         if ((!bd->lock_border) || (!bd->client.border.name))
9303           bd->client.border.changed = 1;
9304
9305         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9306           {
9307              if (!bd->client.netwm.state.skip_pager)
9308                {
9309                   bd->client.netwm.state.skip_pager = 1;
9310                   bd->client.netwm.update.state = 1;
9311                }
9312              if (!bd->client.netwm.state.skip_taskbar)
9313                {
9314                   bd->client.netwm.state.skip_taskbar = 1;
9315                   bd->client.netwm.update.state = 1;
9316                }
9317           }
9318         bd->client.netwm.fetch.type = 0;
9319      }
9320    if (bd->client.icccm.fetch.machine)
9321      {
9322         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9323
9324         if ((!machine) && (bd->client.icccm.client_leader))
9325           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9326
9327         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9328         if (machine) free(machine);
9329
9330         bd->client.icccm.fetch.machine = 0;
9331         rem_change = 1;
9332      }
9333    if (bd->client.icccm.fetch.command)
9334      {
9335         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9336           {
9337              int i;
9338
9339              for (i = 0; i < bd->client.icccm.command.argc; i++)
9340                free(bd->client.icccm.command.argv[i]);
9341              free(bd->client.icccm.command.argv);
9342           }
9343         bd->client.icccm.command.argc = 0;
9344         bd->client.icccm.command.argv = NULL;
9345         ecore_x_icccm_command_get(bd->client.win,
9346                                   &(bd->client.icccm.command.argc),
9347                                   &(bd->client.icccm.command.argv));
9348         if ((bd->client.icccm.client_leader) &&
9349             (!bd->client.icccm.command.argv))
9350           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9351                                     &(bd->client.icccm.command.argc),
9352                                     &(bd->client.icccm.command.argv));
9353         bd->client.icccm.fetch.command = 0;
9354         rem_change = 1;
9355      }
9356    if (bd->client.icccm.fetch.hints)
9357      {
9358         Eina_Bool accepts_focus, is_urgent;
9359
9360         accepts_focus = EINA_TRUE;
9361         is_urgent = EINA_FALSE;
9362         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9363         if (ecore_x_icccm_hints_get(bd->client.win,
9364                                     &accepts_focus,
9365                                     &bd->client.icccm.initial_state,
9366                                     &bd->client.icccm.icon_pixmap,
9367                                     &bd->client.icccm.icon_mask,
9368                                     &bd->client.icccm.icon_window,
9369                                     &bd->client.icccm.window_group,
9370                                     &is_urgent))
9371           {
9372              bd->client.icccm.accepts_focus = accepts_focus;
9373              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9374                change_urgent = 1;
9375              bd->client.icccm.urgent = is_urgent;
9376
9377              /* If this is a new window, set the state as requested. */
9378              if ((bd->new_client) &&
9379                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9380                {
9381                   e_border_iconify(bd);
9382                   e_border_hide(bd, 1);
9383                }
9384           }
9385         bd->client.icccm.fetch.hints = 0;
9386         rem_change = 1;
9387      }
9388    if (bd->client.icccm.fetch.size_pos_hints)
9389      {
9390         Eina_Bool request_pos;
9391
9392         request_pos = EINA_FALSE;
9393         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9394                                              &request_pos,
9395                                              &bd->client.icccm.gravity,
9396                                              &bd->client.icccm.min_w,
9397                                              &bd->client.icccm.min_h,
9398                                              &bd->client.icccm.max_w,
9399                                              &bd->client.icccm.max_h,
9400                                              &bd->client.icccm.base_w,
9401                                              &bd->client.icccm.base_h,
9402                                              &bd->client.icccm.step_w,
9403                                              &bd->client.icccm.step_h,
9404                                              &bd->client.icccm.min_aspect,
9405                                              &bd->client.icccm.max_aspect))
9406           {
9407              bd->client.icccm.request_pos = request_pos;
9408           }
9409         else
9410           {
9411           }
9412         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9413         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9414         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9415         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9416         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9417         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9418         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9419         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9420         // if doing a resize, fix it up
9421         if (bd->resize_mode != RESIZE_NONE)
9422           {
9423              int x, y, w, h, new_w, new_h;
9424
9425              x = bd->x;
9426              y = bd->y;
9427              w = bd->w;
9428              h = bd->h;
9429              new_w = w;
9430              new_h = h;
9431              e_border_resize_limit(bd, &new_w, &new_h);
9432              if ((bd->resize_mode == RESIZE_TL) ||
9433                  (bd->resize_mode == RESIZE_L) ||
9434                  (bd->resize_mode == RESIZE_BL))
9435                x += (w - new_w);
9436              if ((bd->resize_mode == RESIZE_TL) ||
9437                  (bd->resize_mode == RESIZE_T) ||
9438                  (bd->resize_mode == RESIZE_TR))
9439                y += (h - new_h);
9440              e_border_move_resize(bd, x, y, new_w, new_h);
9441           }
9442         bd->client.icccm.fetch.size_pos_hints = 0;
9443         rem_change = 1;
9444      }
9445    if (bd->client.icccm.fetch.protocol)
9446      {
9447         int i, num;
9448         Ecore_X_WM_Protocol *proto;
9449
9450         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9451         if (proto)
9452           {
9453              for (i = 0; i < num; i++)
9454                {
9455                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9456                     bd->client.icccm.delete_request = 1;
9457                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9458                     bd->client.icccm.take_focus = 1;
9459                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9460                     bd->client.netwm.ping = 1;
9461                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9462                     {
9463                        bd->client.netwm.sync.request = 1;
9464                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9465                                                            &bd->client.netwm.sync.counter))
9466                          bd->client.netwm.sync.request = 0;
9467                     }
9468                }
9469              free(proto);
9470           }
9471         if (bd->client.netwm.ping)
9472           e_border_ping(bd);
9473         else
9474           {
9475              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9476              bd->ping_poller = NULL;
9477           }
9478         bd->client.icccm.fetch.protocol = 0;
9479      }
9480    if (bd->client.icccm.fetch.transient_for)
9481      {
9482         /* TODO: What do to if the transient for isn't mapped yet? */
9483         E_Border *bd_parent = NULL;
9484 #ifdef _F_DEICONIFY_APPROVE_
9485         Eina_Bool change_parent = EINA_FALSE;
9486 #endif
9487
9488         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9489         if (bd->client.icccm.transient_for)
9490           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9491         /* If we already have a parent, remove it */
9492         if (bd->parent)
9493           {
9494              if (bd_parent != bd->parent)
9495                {
9496                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9497                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9498                   bd->parent = NULL;
9499                }
9500              else
9501                bd_parent = NULL;
9502           }
9503         if ((bd_parent) && (bd_parent != bd) &&
9504             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9505           {
9506              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9507              bd->parent = bd_parent;
9508 #ifdef _F_DEICONIFY_APPROVE_
9509              change_parent = EINA_TRUE;
9510 #endif
9511           }
9512         if (bd->parent)
9513           {
9514              e_border_layer_set(bd, bd->parent->layer);
9515              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9516                {
9517                   Ecore_X_Window_Attributes attr;
9518                   bd->parent->modal = bd;
9519                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9520                   bd->parent->saved.event_mask = attr.event_mask.mine;
9521                   bd->parent->lock_close = 1;
9522                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9523                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9524                }
9525
9526              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9527                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9528                bd->take_focus = 1;
9529           }
9530
9531 #ifdef _F_DEICONIFY_APPROVE_
9532         if (change_parent)
9533           {
9534              bd->client.e.state.deiconify_approve.render_done = 0;
9535
9536              E_Border *ancestor_bd;
9537              ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
9538              if ((ancestor_bd) &&
9539                  (!e_object_is_del(E_OBJECT(ancestor_bd))))
9540                {
9541                   ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
9542                   bd->client.e.state.deiconify_approve.ancestor = NULL;
9543
9544                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
9545                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
9546                     {
9547                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
9548                          {
9549                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
9550                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
9551                             e_border_uniconify(ancestor_bd);
9552                          }
9553                     }
9554                }
9555           }
9556 #endif
9557         bd->client.icccm.fetch.transient_for = 0;
9558         rem_change = 1;
9559      }
9560    if (bd->client.icccm.fetch.window_role)
9561      {
9562         char *role = ecore_x_icccm_window_role_get(bd->client.win);
9563         eina_stringshare_replace(&bd->client.icccm.window_role, role);
9564         if (role) free(role);
9565
9566         bd->client.icccm.fetch.window_role = 0;
9567         rem_change = 1;
9568      }
9569    if (bd->client.icccm.fetch.icon_name)
9570      {
9571         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
9572         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
9573         if (icon_name) free(icon_name);
9574
9575         bd->client.icccm.fetch.icon_name = 0;
9576         rem_change = 1;
9577      }
9578    if (bd->client.netwm.fetch.icon_name)
9579      {
9580         char *icon_name;
9581         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
9582         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
9583         if (icon_name) free(icon_name);
9584
9585         bd->client.netwm.fetch.icon_name = 0;
9586         rem_change = 1;
9587      }
9588    if (bd->client.netwm.fetch.icon)
9589      {
9590         int i;
9591         if (bd->client.netwm.icons)
9592           {
9593              for (i = 0; i < bd->client.netwm.num_icons; i++)
9594                {
9595                   free(bd->client.netwm.icons[i].data);
9596                   bd->client.netwm.icons[i].data = NULL;
9597                }
9598              free(bd->client.netwm.icons);
9599           }
9600         bd->client.netwm.icons = NULL;
9601         bd->client.netwm.num_icons = 0;
9602         if (ecore_x_netwm_icons_get(bd->client.win,
9603                                      &bd->client.netwm.icons,
9604                                      &bd->client.netwm.num_icons))
9605           {
9606              // unless the rest of e17 uses border icons OTHER than icon #0
9607              // then free the rest that we don't need anymore.
9608              for (i = 1; i < bd->client.netwm.num_icons; i++)
9609                {
9610                   free(bd->client.netwm.icons[i].data);
9611                   bd->client.netwm.icons[i].data = NULL;
9612                }
9613              bd->client.netwm.num_icons = 1;
9614              bd->changes.icon = 1;
9615           }
9616         bd->client.netwm.fetch.icon = 0;
9617      }
9618    if (bd->client.netwm.fetch.user_time)
9619      {
9620         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
9621         bd->client.netwm.fetch.user_time = 0;
9622      }
9623    if (bd->client.netwm.fetch.strut)
9624      {
9625         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
9626                                              &bd->client.netwm.strut.left,
9627                                              &bd->client.netwm.strut.right,
9628                                              &bd->client.netwm.strut.top,
9629                                              &bd->client.netwm.strut.bottom,
9630                                              &bd->client.netwm.strut.left_start_y,
9631                                              &bd->client.netwm.strut.left_end_y,
9632                                              &bd->client.netwm.strut.right_start_y,
9633                                              &bd->client.netwm.strut.right_end_y,
9634                                              &bd->client.netwm.strut.top_start_x,
9635                                              &bd->client.netwm.strut.top_end_x,
9636                                              &bd->client.netwm.strut.bottom_start_x,
9637                                              &bd->client.netwm.strut.bottom_end_x))
9638           {
9639              ecore_x_netwm_strut_get(bd->client.win,
9640                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
9641                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
9642
9643              bd->client.netwm.strut.left_start_y = 0;
9644              bd->client.netwm.strut.left_end_y = 0;
9645              bd->client.netwm.strut.right_start_y = 0;
9646              bd->client.netwm.strut.right_end_y = 0;
9647              bd->client.netwm.strut.top_start_x = 0;
9648              bd->client.netwm.strut.top_end_x = 0;
9649              bd->client.netwm.strut.bottom_start_x = 0;
9650              bd->client.netwm.strut.bottom_end_x = 0;
9651           }
9652         bd->client.netwm.fetch.strut = 0;
9653      }
9654    if (bd->client.qtopia.fetch.soft_menu)
9655      {
9656         e_hints_window_qtopia_soft_menu_get(bd);
9657         bd->client.qtopia.fetch.soft_menu = 0;
9658         rem_change = 1;
9659      }
9660    if (bd->client.qtopia.fetch.soft_menus)
9661      {
9662         e_hints_window_qtopia_soft_menus_get(bd);
9663         bd->client.qtopia.fetch.soft_menus = 0;
9664         rem_change = 1;
9665      }
9666    if (bd->client.vkbd.fetch.state)
9667      {
9668         e_hints_window_virtual_keyboard_state_get(bd);
9669         bd->client.vkbd.fetch.state = 0;
9670         rem_change = 1;
9671      }
9672    if (bd->client.vkbd.fetch.vkbd)
9673      {
9674         e_hints_window_virtual_keyboard_get(bd);
9675         bd->client.vkbd.fetch.vkbd = 0;
9676         rem_change = 1;
9677      }
9678    if (bd->client.illume.conformant.fetch.conformant)
9679      {
9680         bd->client.illume.conformant.conformant =
9681           ecore_x_e_illume_conformant_get(bd->client.win);
9682         bd->client.illume.conformant.fetch.conformant = 0;
9683      }
9684    if (bd->client.illume.quickpanel.fetch.state)
9685      {
9686         bd->client.illume.quickpanel.state =
9687           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
9688         bd->client.illume.quickpanel.fetch.state = 0;
9689      }
9690    if (bd->client.illume.quickpanel.fetch.quickpanel)
9691      {
9692         bd->client.illume.quickpanel.quickpanel =
9693           ecore_x_e_illume_quickpanel_get(bd->client.win);
9694         bd->client.illume.quickpanel.fetch.quickpanel = 0;
9695      }
9696    if (bd->client.illume.quickpanel.fetch.priority.major)
9697      {
9698         bd->client.illume.quickpanel.priority.major =
9699           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
9700         bd->client.illume.quickpanel.fetch.priority.major = 0;
9701      }
9702    if (bd->client.illume.quickpanel.fetch.priority.minor)
9703      {
9704         bd->client.illume.quickpanel.priority.minor =
9705           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
9706         bd->client.illume.quickpanel.fetch.priority.minor = 0;
9707      }
9708    if (bd->client.illume.quickpanel.fetch.zone)
9709      {
9710         bd->client.illume.quickpanel.zone =
9711           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
9712         bd->client.illume.quickpanel.fetch.zone = 0;
9713      }
9714    if (bd->client.illume.drag.fetch.drag)
9715      {
9716         bd->client.illume.drag.drag =
9717           ecore_x_e_illume_drag_get(bd->client.win);
9718         bd->client.illume.drag.fetch.drag = 0;
9719      }
9720    if (bd->client.illume.drag.fetch.locked)
9721      {
9722         bd->client.illume.drag.locked =
9723           ecore_x_e_illume_drag_locked_get(bd->client.win);
9724         bd->client.illume.drag.fetch.locked = 0;
9725      }
9726    if (bd->client.illume.win_state.fetch.state)
9727      {
9728         bd->client.illume.win_state.state =
9729            ecore_x_e_illume_window_state_get(bd->client.win);
9730         bd->client.illume.win_state.fetch.state = 0;
9731      }
9732    if (bd->changes.shape)
9733      {
9734         Ecore_X_Rectangle *rects;
9735         int num;
9736
9737         bd->changes.shape = 0;
9738         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
9739         if (rects)
9740           {
9741              int cw = 0, ch = 0;
9742
9743              /* This doesn't fix the race, but makes it smaller. we detect
9744               * this and if cw and ch != client w/h then mark this as needing
9745               * a shape change again to fixup next event loop.
9746               */
9747              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9748              if ((cw != bd->client.w) || (ch != bd->client.h))
9749                bd->changes.shape = 1;
9750              if ((num == 1) &&
9751                  (rects[0].x == 0) &&
9752                  (rects[0].y == 0) &&
9753                  ((int)rects[0].width == cw) &&
9754                  ((int)rects[0].height == ch))
9755                {
9756                   if (bd->client.shaped)
9757                     {
9758                        bd->client.shaped = 0;
9759                        if (!bd->bordername)
9760                          bd->client.border.changed = 1;
9761                     }
9762                }
9763              else
9764                {
9765                   if (!bd->client.shaped)
9766                     {
9767                        bd->client.shaped = 1;
9768                        if (!bd->bordername)
9769                          bd->client.border.changed = 1;
9770                     }
9771                }
9772              free(rects);
9773           }
9774         else
9775           {
9776              // FIXME: no rects i think can mean... totally empty window
9777              bd->client.shaped = 0;
9778              if (!bd->bordername)
9779                bd->client.border.changed = 1;
9780           }
9781         bd->need_shape_merge = 1;
9782      }
9783    if (bd->changes.shape_input)
9784      {
9785         Ecore_X_Rectangle *rects;
9786         int num;
9787
9788         bd->changes.shape_input = 0;
9789         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
9790         if (rects)
9791           {
9792              int cw = 0, ch = 0;
9793
9794              /* This doesn't fix the race, but makes it smaller. we detect
9795               * this and if cw and ch != client w/h then mark this as needing
9796               * a shape change again to fixup next event loop.
9797               */
9798              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9799              if ((cw != bd->client.w) || (ch != bd->client.h))
9800                bd->changes.shape_input = 1;
9801              if ((num == 1) &&
9802                  (rects[0].x == 0) &&
9803                  (rects[0].y == 0) &&
9804                  ((int)rects[0].width == cw) &&
9805                  ((int)rects[0].height == ch))
9806                {
9807                   if (bd->shaped_input)
9808                     {
9809                        bd->shaped_input = 0;
9810                        if (!bd->bordername)
9811                          bd->client.border.changed = 1;
9812                     }
9813                }
9814              else
9815                {
9816                   if (!bd->shaped_input)
9817                     {
9818                        bd->shaped_input = 1;
9819                        if (!bd->bordername)
9820                          bd->client.border.changed = 1;
9821                     }
9822                }
9823              free(rects);
9824           }
9825         else
9826           {
9827              bd->shaped_input = 1;
9828              if (!bd->bordername)
9829                bd->client.border.changed = 1;
9830           }
9831         bd->need_shape_merge = 1;
9832      }
9833    if (bd->client.mwm.fetch.hints)
9834      {
9835         int pb;
9836
9837         bd->client.mwm.exists =
9838           ecore_x_mwm_hints_get(bd->client.win,
9839                                 &bd->client.mwm.func,
9840                                 &bd->client.mwm.decor,
9841                                 &bd->client.mwm.input);
9842         pb = bd->client.mwm.borderless;
9843         bd->client.mwm.borderless = 0;
9844         if (bd->client.mwm.exists)
9845           {
9846              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
9847                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
9848                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
9849                bd->client.mwm.borderless = 1;
9850           }
9851         if (bd->client.mwm.borderless != pb)
9852           {
9853              if ((!bd->lock_border) || (!bd->client.border.name))
9854                bd->client.border.changed = 1;
9855           }
9856         bd->client.mwm.fetch.hints = 0;
9857         rem_change = 1;
9858      }
9859    if (bd->client.e.fetch.video_parent)
9860      {
9861         /* unlinking child/parent */
9862         if (bd->client.e.state.video_parent_border != NULL)
9863           {
9864              bd->client.e.state.video_parent_border->client.e.state.video_child =
9865                eina_list_remove
9866                (bd->client.e.state.video_parent_border->client.e.state.video_child,
9867                    bd);
9868           }
9869
9870         ecore_x_window_prop_card32_get(bd->client.win,
9871                                        ECORE_X_ATOM_E_VIDEO_PARENT,
9872                                        &bd->client.e.state.video_parent,
9873                                        1);
9874
9875         /* linking child/parent */
9876         if (bd->client.e.state.video_parent != 0)
9877           {
9878              E_Border *tmp;
9879              Eina_List *l;
9880
9881              EINA_LIST_FOREACH(borders, l, tmp)
9882                if (tmp->client.win == bd->client.e.state.video_parent)
9883                  {
9884                     /* fprintf(stderr, "child added to parent \\o/\n"); */
9885                     bd->client.e.state.video_parent_border = tmp;
9886                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
9887                                                                        bd);
9888                     if (bd->desk != tmp->desk)
9889                       e_border_desk_set(bd, tmp->desk);
9890                     break;
9891                  }
9892           }
9893
9894         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
9895
9896         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
9897         rem_change = 1;
9898      }
9899    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
9900      {
9901         unsigned int xy[2];
9902
9903         ecore_x_window_prop_card32_get(bd->client.win,
9904                                        ECORE_X_ATOM_E_VIDEO_POSITION,
9905                                        xy,
9906                                        2);
9907         bd->client.e.state.video_position.x = xy[0];
9908         bd->client.e.state.video_position.y = xy[1];
9909         bd->client.e.state.video_position.updated = 1;
9910         bd->client.e.fetch.video_position = 0;
9911         bd->x = bd->client.e.state.video_position.x;
9912         bd->y = bd->client.e.state.video_position.y;
9913
9914         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
9915      }
9916    if (bd->client.netwm.update.state)
9917      {
9918         e_hints_window_state_set(bd);
9919         /* Some stats might change the border, like modal */
9920         if (((!bd->lock_border) || (!bd->client.border.name)) &&
9921             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
9922           {
9923              bd->client.border.changed = 1;
9924           }
9925         if (bd->parent)
9926           {
9927              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9928                {
9929                   bd->parent->modal = bd;
9930                   if (bd->parent->focused)
9931                     e_border_focus_set(bd, 1, 1);
9932                }
9933           }
9934         else if (bd->leader)
9935           {
9936              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9937                {
9938                   bd->leader->modal = bd;
9939                   if (bd->leader->focused)
9940                     e_border_focus_set(bd, 1, 1);
9941                   else
9942                     {
9943                        Eina_List *l;
9944                        E_Border *child;
9945
9946                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9947                          {
9948                             if ((child != bd) && (child->focused))
9949                               e_border_focus_set(bd, 1, 1);
9950                          }
9951                     }
9952                }
9953           }
9954         bd->client.netwm.update.state = 0;
9955      }
9956
9957    if (bd->new_client)
9958      {
9959         E_Event_Border_Add *ev;
9960         E_Exec_Instance *inst;
9961
9962         ev = E_NEW(E_Event_Border_Add, 1);
9963         ev->border = bd;
9964         e_object_ref(E_OBJECT(bd));
9965         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
9966         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
9967
9968         if ((!bd->lock_border) || (!bd->client.border.name))
9969           bd->client.border.changed = 1;
9970
9971           {
9972              char *str = NULL;
9973
9974              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
9975                  ((bd->client.icccm.client_leader > 0) &&
9976                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
9977                 )
9978                {
9979                   if (!strncmp(str, "E_START|", 8))
9980                     {
9981                        int id;
9982
9983                        id = atoi(str + 8);
9984                        if (id > 0) bd->client.netwm.startup_id = id;
9985                     }
9986                   free(str);
9987                }
9988           }
9989         /* It's ok not to have fetch flag, should only be set on startup
9990          *     * and not changed. */
9991         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
9992           {
9993              if (bd->client.icccm.client_leader)
9994                {
9995                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
9996                     bd->client.netwm.pid = -1;
9997                }
9998              else
9999                bd->client.netwm.pid = -1;
10000           }
10001
10002         if (!bd->re_manage)
10003           {
10004              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
10005                                                         bd->client.netwm.pid);
10006              if ((inst) && (inst->used == 0))
10007                {
10008                   E_Zone *zone;
10009                   E_Desk *desk;
10010
10011                   inst->used++;
10012                   zone = e_container_zone_number_get(bd->zone->container,
10013                                                      inst->screen);
10014                   if (zone) e_border_zone_set(bd, zone);
10015                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
10016                                           inst->desk_y);
10017                   if (desk) e_border_desk_set(bd, desk);
10018                   e_exec_instance_found(inst);
10019                }
10020
10021              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
10022                {
10023                   E_Border *bdl = NULL;
10024
10025                   bdl = bd->parent;
10026                   if (!bdl)
10027                     {
10028                        if (bd->leader) bdl = bd->leader;
10029                     }
10030                   if (!bdl)
10031                     {
10032                        E_Border *child;
10033                        E_Border_List *bl;
10034
10035                        bl = e_container_border_list_first(bd->zone->container);
10036                        while ((child = e_container_border_list_next(bl)))
10037                          {
10038                             if (child == bd) continue;
10039                             if (e_object_is_del(E_OBJECT(child))) continue;
10040                             if ((bd->client.icccm.client_leader) &&
10041                                 (child->client.icccm.client_leader ==
10042                                     bd->client.icccm.client_leader))
10043                               {
10044                                  bdl = child;
10045                                  break;
10046                               }
10047                          }
10048                        e_container_border_list_free(bl);
10049                     }
10050                   if (bdl)
10051                     {
10052                        if (bdl->zone)
10053                          e_border_zone_set(bd, bdl->zone);
10054                        if (bdl->desk)
10055                          e_border_desk_set(bd, bdl->desk);
10056                        else
10057                          e_border_stick(bd);
10058                     }
10059                }
10060           }
10061      }
10062
10063 #ifdef _F_USE_DESK_WINDOW_PROFILE_
10064    if (need_desk_set)
10065      {
10066         E_Container *con = bd->zone->container;
10067         E_Desk *desk = NULL;
10068         Eina_List *l;
10069         const char *str;
10070         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
10071           {
10072              desk = e_container_desk_window_profile_get(con, str);
10073              if (desk)
10074                {
10075                   if (bd->desk != desk)
10076                     {
10077                        bd->client.e.state.profile = eina_stringshare_add(str);
10078                        if (bd->zone != desk->zone)
10079                          e_border_zone_set(bd, desk->zone);
10080                        e_border_desk_set(bd, desk);
10081                     }
10082                   break;
10083                }
10084           }
10085      }
10086 #endif
10087 #ifdef _F_ZONE_WINDOW_ROTATION_
10088    if ((e_config->wm_win_rotation) &&
10089        (need_rotation_set))
10090      {
10091         ELB(ELBT_ROT, "NEED ROT", bd->client.win);
10092         Eina_Bool _rot = _e_border_rotation_check(bd);
10093         /* check whether rotation is available for sub borders such as prediction and magnifier */
10094         if (_rot)
10095           {
10096              Eina_List *ll;
10097              E_Border *_child;
10098              Eina_List *_list = _e_border_sub_borders_new(bd);
10099              EINA_LIST_FOREACH(_list, ll, _child)
10100                {
10101                   if ((_child->client.e.state.rot.support) ||
10102                       (_child->client.e.state.rot.app_set))
10103                     _e_border_rotation_check(_child);
10104                }
10105              eina_list_free(_list);
10106           }
10107      }
10108 #endif
10109
10110    /* PRE_POST_FETCH calls e_remember apply for new client */
10111    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
10112    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
10113    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
10114
10115    if (bd->need_reparent)
10116      {
10117         if (!bd->internal)
10118           ecore_x_window_save_set_add(bd->client.win);
10119         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
10120         if (bd->visible)
10121           {
10122              if ((bd->new_client) && (bd->internal) &&
10123                  (bd->internal_ecore_evas))
10124                ecore_evas_show(bd->internal_ecore_evas);
10125              ecore_x_window_show(bd->client.win);
10126           }
10127         bd->need_reparent = 0;
10128      }
10129
10130    if ((bd->client.border.changed) && (!bd->shaded) &&
10131        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10132      {
10133         const char *bordername;
10134
10135         if (bd->fullscreen)
10136           bordername = "borderless";
10137         else if (bd->bordername)
10138           bordername = bd->bordername;
10139         else if ((bd->client.mwm.borderless) || (bd->borderless))
10140           bordername = "borderless";
10141         else if (((bd->client.icccm.transient_for != 0) ||
10142                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
10143                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10144                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10145           bordername = "noresize_dialog";
10146         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10147                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10148           bordername = "noresize";
10149         else if (bd->client.shaped)
10150           bordername = "shaped";
10151         else if ((!bd->client.icccm.accepts_focus) &&
10152                  (!bd->client.icccm.take_focus))
10153           bordername = "nofocus";
10154         else if (bd->client.icccm.urgent)
10155           bordername = "urgent";
10156         else if ((bd->client.icccm.transient_for != 0) ||
10157                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10158           bordername = "dialog";
10159         else if (bd->client.netwm.state.modal)
10160           bordername = "modal";
10161         else if ((bd->client.netwm.state.skip_taskbar) ||
10162                  (bd->client.netwm.state.skip_pager))
10163           bordername = "skipped";
10164         else if ((bd->internal) && (bd->client.icccm.class) &&
10165                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
10166           bordername = "internal_fileman";
10167         else
10168           bordername = e_config->theme_default_border_style;
10169         if (!bordername) bordername = "default";
10170
10171         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
10172           {
10173              Evas_Object *o;
10174              char buf[4096];
10175              int ok;
10176
10177              bd->changes.border = 1;
10178              eina_stringshare_replace(&bd->client.border.name, bordername);
10179
10180              if (bd->bg_object)
10181                {
10182                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
10183                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
10184                   bd->changes.size = 1;
10185                   evas_object_del(bd->bg_object);
10186                }
10187              o = edje_object_add(bd->bg_evas);
10188              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
10189              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10190              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
10191                {
10192                   if (bd->client.border.name != e_config->theme_default_border_style)
10193                     {
10194                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
10195                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10196                     }
10197                   if (!ok)
10198                     {
10199                        ok = e_theme_edje_object_set(o, "base/theme/borders",
10200                                                     "e/widgets/border/default/border");
10201                        if (ok)
10202                          {
10203                             /* Reset default border style to default */
10204                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
10205                             e_config_save_queue();
10206                          }
10207                     }
10208                }
10209
10210              bd->shaped = 0;
10211              if (ok)
10212                {
10213                   const char *shape_option, *argb_option;
10214                   int use_argb = 0;
10215
10216                   bd->bg_object = o;
10217
10218                   if ((e_config->use_composite) && (!bd->client.argb))
10219                     {
10220                        argb_option = edje_object_data_get(o, "argb");
10221                        if ((argb_option) && (!strcmp(argb_option, "1")))
10222                          use_argb = 1;
10223
10224                        if (use_argb != bd->argb)
10225                          _e_border_frame_replace(bd, use_argb);
10226
10227                        o = bd->bg_object;
10228                     }
10229
10230                   if (!bd->argb)
10231                     {
10232                        shape_option = edje_object_data_get(o, "shaped");
10233                        if ((shape_option) && (!strcmp(shape_option, "1")))
10234                          bd->shaped = 1;
10235                     }
10236
10237                   if (bd->client.netwm.name)
10238                     edje_object_part_text_set(o, "e.text.title",
10239                                               bd->client.netwm.name);
10240                   else if (bd->client.icccm.title)
10241                     edje_object_part_text_set(o, "e.text.title",
10242                                               bd->client.icccm.title);
10243                }
10244              else
10245                {
10246                   evas_object_del(o);
10247                   bd->bg_object = NULL;
10248                }
10249
10250              _e_border_client_inset_calc(bd);
10251
10252              bd->w += (bd->client_inset.l + bd->client_inset.r);
10253              bd->h += (bd->client_inset.t + bd->client_inset.b);
10254              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
10255              bd->changes.size = 1;
10256              /*  really needed ? */
10257              ecore_x_window_move(bd->client.shell_win,
10258                                  bd->client_inset.l,
10259                                  bd->client_inset.t);
10260
10261              if (bd->maximized != E_MAXIMIZE_NONE)
10262                {
10263                   E_Maximize maximized = bd->maximized;
10264
10265                   /* to force possible resizes */
10266                   bd->maximized = E_MAXIMIZE_NONE;
10267
10268                   _e_border_maximize(bd, maximized);
10269
10270                   /* restore maximized state */
10271                   bd->maximized = maximized;
10272
10273                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
10274                                                bd->maximized & E_MAXIMIZE_VERTICAL);
10275                }
10276              if (bd->bg_object)
10277                {
10278                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
10279                                                   _e_border_cb_signal_bind, bd);
10280                   if (bd->focused)
10281                     {
10282                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
10283                        if (bd->icon_object)
10284                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10285                     }
10286                   if (bd->shaded)
10287                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
10288                   if (bd->sticky)
10289                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
10290                   if (bd->hung)
10291                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
10292                   // FIXME: in eval -do differently
10293                   //         edje_object_message_signal_process(bd->bg_object);
10294                   //         e_border_frame_recalc(bd);
10295
10296                   evas_object_move(bd->bg_object, 0, 0);
10297                   evas_object_resize(bd->bg_object, bd->w, bd->h);
10298                   evas_object_show(bd->bg_object);
10299                }
10300           }
10301         bd->client.border.changed = 0;
10302
10303         if (bd->icon_object)
10304           {
10305              if (bd->bg_object)
10306                {
10307                   evas_object_show(bd->icon_object);
10308                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10309                }
10310              else
10311                evas_object_hide(bd->icon_object);
10312           }
10313      }
10314
10315    if (rem_change) e_remember_update(bd);
10316
10317    if (change_urgent)
10318      {
10319         E_Event_Border_Urgent_Change *ev;
10320
10321         if (bd->client.icccm.urgent)
10322           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
10323         else
10324           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
10325
10326         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
10327         ev->border = bd;
10328         e_object_ref(E_OBJECT(bd));
10329         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
10330                         _e_border_event_border_urgent_change_free, NULL);
10331      }
10332
10333    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10334 }
10335
10336 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10337 static void
10338 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10339 {
10340    E_Border* temp_bd = NULL;
10341    E_Border* top_focusable_bd = NULL;
10342    Eina_Bool is_fully_obscured = EINA_FALSE;
10343    Ecore_X_XRegion *visible_region = NULL;
10344    Ecore_X_XRegion *win_region = NULL;
10345    Ecore_X_Rectangle visible_rect, win_rect;
10346    E_Border_List *bl;
10347
10348    // set the entire visible region as a root geometry
10349    visible_rect.x = bd->zone->x;
10350    visible_rect.y = bd->zone->y;
10351    visible_rect.width = bd->zone->w;
10352    visible_rect.height = bd->zone->h;
10353
10354    visible_region = ecore_x_xregion_new();
10355    if (!visible_region) return;
10356
10357    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10358
10359    bl = e_container_border_list_last(bd->zone->container);
10360    while ((temp_bd = e_container_border_list_prev(bl)))
10361      {
10362         if (temp_bd == bd) break;
10363
10364         if (temp_bd == focused) continue;
10365         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10366         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10367         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10368             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10369             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10370             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10371             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10372             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10373             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10374           {
10375              if (!top_focusable_bd)
10376                {
10377                   top_focusable_bd = temp_bd;
10378                }
10379
10380              win_rect.x = temp_bd->x;
10381              win_rect.y = temp_bd->y;
10382              win_rect.width = temp_bd->w;
10383              win_rect.height = temp_bd->h;
10384
10385              // if it stick out or is bigger than the entire visible region,
10386              // clip it by the entire visible's geometry.
10387              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10388                                   win_rect.width, win_rect.height,
10389                                   visible_rect.x, visible_rect.y,
10390                                   (int)(visible_rect.width), (int)(visible_rect.height));
10391
10392              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10393                {
10394                   win_region = ecore_x_xregion_new();
10395                   if (win_region)
10396                     {
10397                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10398                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10399                        ecore_x_xregion_free(win_region);
10400                        win_region = NULL;
10401
10402                        if (ecore_x_xregion_is_empty(visible_region))
10403                          {
10404                             is_fully_obscured = EINA_TRUE;
10405                             break;
10406                          }
10407                     }
10408                }
10409           }
10410      }
10411
10412    if (is_fully_obscured == EINA_TRUE)
10413      {
10414         e_border_focus_set(top_focusable_bd, 1, 1);
10415      }
10416    else
10417      {
10418         e_border_focus_set(bd, 1, 1);
10419      }
10420
10421    if (visible_region) ecore_x_xregion_free(visible_region);
10422    e_container_border_list_free(bl);
10423 }
10424
10425 static void
10426 _e_border_latest_stacked_focus(E_Border *bd)
10427 {
10428    E_Border *temp_bd;
10429    int root_w, root_h;
10430
10431    root_w = bd->zone->w;
10432    root_h = bd->zone->h;
10433
10434    Eina_List *l;
10435    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10436      {
10437         if (bd == temp_bd) continue;
10438         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10439         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10440
10441         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10442             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10443             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10444             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10445             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10446             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10447             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10448           {
10449              _e_border_latest_stacked_focus_check_set(temp_bd);
10450              break;
10451           }
10452      }
10453 }
10454
10455 static void
10456 _e_border_check_stack (E_Border *bd)
10457 {
10458    E_Border* temp_bd = NULL;
10459    E_Border* top_bd = NULL;
10460    int passed_focus = 0;
10461    int passed = 0;
10462    int root_w = bd->zone->w;
10463    int root_h = bd->zone->h;
10464
10465    E_Border_List *bl;
10466    bl = e_container_border_list_last(bd->zone->container);
10467    while ((temp_bd = e_container_border_list_prev(bl)))
10468      {
10469         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10470         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10471         if ((temp_bd != bd) &&
10472             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10473
10474         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10475            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10476            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10477            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10478            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10479            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10480            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10481           {
10482              if (bd == temp_bd)
10483                {
10484                   if (!passed)
10485                     {
10486                        e_border_focus_set_with_pointer(bd);
10487                        break;
10488                     }
10489                   else
10490                     {
10491                        if (!passed_focus)
10492                          {
10493                             e_border_focus_set_with_pointer(top_bd);
10494                          }
10495                        break;
10496                     }
10497                }
10498              else
10499                {
10500                   if (!passed)
10501                     {
10502                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10503                          {
10504                             if (!bd->lock_focus_out)
10505                               {
10506                                  e_border_focus_latest_set(bd);
10507                               }
10508                          }
10509                     }
10510                }
10511
10512              if (!passed)
10513                {
10514                   passed = 1;
10515                   top_bd = temp_bd;
10516                }
10517
10518              if (temp_bd == focused)
10519                {
10520                   passed_focus = 1;
10521                }
10522           }
10523      }
10524    e_container_border_list_free(bl);
10525 }
10526
10527 static void
10528 _e_border_focus_top_stack_set(E_Border* bd)
10529 {
10530    E_Border *temp_bd;
10531    int root_w, root_h;
10532
10533    root_w = bd->zone->w;
10534    root_h = bd->zone->h;
10535
10536    E_Border_List *bl;
10537    bl = e_container_border_list_last(bd->zone->container);
10538    while ((temp_bd = e_container_border_list_prev(bl)))
10539      {
10540         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10541         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10542         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
10543
10544         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10545            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10546            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10547            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10548            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10549            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10550            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10551           {
10552              if (!temp_bd->focused)
10553                {
10554                   /* this border is the top of the latest stack */
10555                   e_border_focus_set (temp_bd, 1, 1);
10556                }
10557              break;
10558           }
10559      }
10560    e_container_border_list_free(bl);
10561 }
10562 #endif
10563
10564 static void
10565 _e_border_eval(E_Border *bd)
10566 {
10567    E_Event_Border_Property *event;
10568    E_Border_Pending_Move_Resize *pnd;
10569    int rem_change = 0;
10570    int send_event = 1;
10571
10572    if (e_object_is_del(E_OBJECT(bd)))
10573      {
10574         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
10575         bd->changed = 0;
10576         return;
10577      }
10578
10579    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
10580
10581    if (bd->new_client)
10582      {
10583         int zx = 0, zy = 0, zw = 0, zh = 0;
10584
10585         if (bd->zone)
10586           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
10587
10588         /*
10589          * Limit maximum size of windows to useful geometry
10590          */
10591         // TODO: temoporary limited maximize algorithm
10592         // ->
10593         /*if (bd->w > zw)
10594           rw = zw;
10595           else
10596           rw = bd->w;
10597
10598           if (bd->h > zh)
10599           rh = zh;
10600           else
10601           rh = bd->h;
10602
10603           if ((rw != bd->w) || (rh != bd->h))
10604           {
10605           bd->w = rw;
10606           bd->h = rh;
10607           e_border_resize (bd, bd->w, bd->h);
10608           }*/
10609         // <-
10610
10611         if (bd->re_manage)
10612           {
10613              bd->x -= bd->client_inset.l;
10614              bd->y -= bd->client_inset.t;
10615              bd->changes.pos = 1;
10616              bd->placed = 1;
10617           }
10618         else if ((!bd->placed) && (bd->client.icccm.request_pos))
10619           {
10620
10621              Ecore_X_Window_Attributes *att;
10622              int bw;
10623
10624              att = &bd->client.initial_attributes;
10625              bw = att->border * 2;
10626              switch (bd->client.icccm.gravity)
10627                {
10628                 case ECORE_X_GRAVITY_N:
10629                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10630                    bd->y = att->y;
10631                    break;
10632
10633                 case ECORE_X_GRAVITY_NE:
10634                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10635                    bd->y = att->y;
10636                    break;
10637
10638                 case ECORE_X_GRAVITY_E:
10639                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10640                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10641                    break;
10642
10643                 case ECORE_X_GRAVITY_SE:
10644                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10645                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10646                    break;
10647
10648                 case ECORE_X_GRAVITY_S:
10649                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10650                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10651                    break;
10652
10653                 case ECORE_X_GRAVITY_SW:
10654                    bd->x = att->x;
10655                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10656                    break;
10657
10658                 case ECORE_X_GRAVITY_W:
10659                    bd->x = att->x;
10660                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10661                    break;
10662
10663                 case ECORE_X_GRAVITY_CENTER:
10664                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10665                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10666                    break;
10667
10668                 case ECORE_X_GRAVITY_NW:
10669                 default:
10670                    bd->x = att->x;
10671                    bd->y = att->y;
10672                }
10673
10674              /*
10675               * This ensures that windows that like to open with a x/y
10676               * position smaller than returned by e_zone_useful_geometry_get()
10677               * are moved to useful positions.
10678               */
10679              // ->
10680              if (e_config->geometry_auto_move)
10681                {
10682                   if (bd->x < zx)
10683                     bd->x = zx;
10684
10685                   if (bd->y < zy)
10686                     bd->y = zy;
10687
10688                   if (bd->x + bd->w > zx + zw)
10689                     bd->x = zx + zw - bd->w;
10690
10691                   if (bd->y + bd->h > zy + zh)
10692                     bd->y = zy + zh - bd->h;
10693                   // <--
10694
10695                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
10696                     {
10697                        bd->changes.pos = 1;
10698                        bd->placed = 1;
10699                     }
10700                }
10701              else
10702                {
10703                   bd->changes.pos = 1;
10704                   bd->placed = 1;
10705                }
10706           }
10707         if (!bd->placed)
10708           {
10709              /* FIXME: special placement for dialogs etc. etc. etc goes
10710               * here */
10711              /* FIXME: what if parent is not on this desktop - or zone? */
10712              if ((bd->parent) && (bd->parent->visible))
10713                {
10714                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
10715                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
10716                   bd->changes.pos = 1;
10717                   bd->placed = 1;
10718                }
10719 #if 0
10720              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10721                {
10722                   /* TODO: Place in center of group */
10723                }
10724 #endif
10725              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
10726                {
10727                   bd->x = zx + ((zw - bd->w) / 2);
10728                   bd->y = zy + ((zh - bd->h) / 2);
10729                   bd->changes.pos = 1;
10730                   bd->placed = 1;
10731                }
10732           }
10733         if (!bd->placed)
10734           {
10735              Eina_List *skiplist = NULL;
10736              int new_x, new_y;
10737
10738              if (zw > bd->w)
10739                new_x = zx + (rand() % (zw - bd->w));
10740              else
10741                new_x = zx;
10742              if (zh > bd->h)
10743                new_y = zy + (rand() % (zh - bd->h));
10744              else
10745                new_y = zy;
10746
10747              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
10748                {
10749                   skiplist = eina_list_append(skiplist, bd);
10750                   if (bd->desk)
10751                     e_place_desk_region_smart(bd->desk, skiplist,
10752                                               bd->x, bd->y, bd->w, bd->h,
10753                                               &new_x, &new_y);
10754                   else
10755                     e_place_zone_region_smart(bd->zone, skiplist,
10756                                               bd->x, bd->y, bd->w, bd->h,
10757                                               &new_x, &new_y);
10758                   eina_list_free(skiplist);
10759                }
10760              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
10761                {
10762                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
10763                                       &new_x, &new_y);
10764                }
10765              else
10766                {
10767                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
10768                                       bd->client_inset.t, &new_x, &new_y);
10769                }
10770              bd->x = new_x;
10771              bd->y = new_y;
10772              bd->changes.pos = 1;
10773           }
10774
10775         EINA_LIST_FREE(bd->pending_move_resize, pnd)
10776           {
10777              if ((!bd->lock_client_location) && (pnd->move))
10778                {
10779                   bd->x = pnd->x;
10780                   bd->y = pnd->y;
10781                   bd->changes.pos = 1;
10782                   bd->placed = 1;
10783                   if (pnd->without_border)
10784                     {
10785                        bd->x -= bd->client_inset.l;
10786                        bd->y -= bd->client_inset.t;
10787                     }
10788                }
10789              if ((!bd->lock_client_size) && (pnd->resize))
10790                {
10791                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
10792                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
10793                   bd->client.w = pnd->w;
10794                   bd->client.h = pnd->h;
10795                   bd->changes.size = 1;
10796                }
10797
10798              free(pnd);
10799           }
10800
10801         /* Recreate state */
10802         e_hints_window_init(bd);
10803         if ((bd->client.e.state.centered) &&
10804             ((!bd->remember) ||
10805              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
10806           {
10807              bd->x = zx + (zw - bd->w) / 2;
10808              bd->y = zy + (zh - bd->h) / 2;
10809              bd->changes.pos = 1;
10810              bd->placed = 1;
10811           }
10812
10813         _e_border_client_move_resize_send(bd);
10814
10815         /* if the explicit geometry request asks for the app to be
10816          * in another zone - well move it there */
10817         {
10818            E_Zone *zone;
10819
10820            zone = e_container_zone_at_point_get(bd->zone->container,
10821                                                 bd->x + (bd->w / 2),
10822                                                 bd->y + (bd->h / 2));
10823            if (!zone)
10824              zone = e_container_zone_at_point_get(bd->zone->container,
10825                                                   bd->x,
10826                                                   bd->y);
10827            if (!zone)
10828              zone = e_container_zone_at_point_get(bd->zone->container,
10829                                                   bd->x + bd->w - 1,
10830                                                   bd->y);
10831            if (!zone)
10832              zone = e_container_zone_at_point_get(bd->zone->container,
10833                                                   bd->x + bd->w - 1,
10834                                                   bd->y + bd->h - 1);
10835            if (!zone)
10836              zone = e_container_zone_at_point_get(bd->zone->container,
10837                                                   bd->x,
10838                                                   bd->y + bd->h - 1);
10839            if ((zone) && (zone != bd->zone))
10840              e_border_zone_set(bd, zone);
10841         }
10842      }
10843
10844    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
10845
10846    /* effect changes to the window border itself */
10847    if ((bd->changes.shading))
10848      {
10849         /*  show at start of unshade (but don't hide until end of shade) */
10850         if (bd->shaded)
10851           ecore_x_window_raise(bd->client.shell_win);
10852         bd->changes.shading = 0;
10853         rem_change = 1;
10854      }
10855    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
10856      {
10857         if (bd->shaded)
10858           ecore_x_window_lower(bd->client.shell_win);
10859         else
10860           ecore_x_window_raise(bd->client.shell_win);
10861         bd->changes.shaded = 0;
10862         rem_change = 1;
10863      }
10864    else if ((bd->changes.shaded) && (bd->changes.pos))
10865      {
10866         if (bd->shaded)
10867           ecore_x_window_lower(bd->client.shell_win);
10868         else
10869           ecore_x_window_raise(bd->client.shell_win);
10870         bd->changes.size = 1;
10871         bd->changes.shaded = 0;
10872         rem_change = 1;
10873      }
10874    else if ((bd->changes.shaded) && (bd->changes.size))
10875      {
10876         if (bd->shaded)
10877           ecore_x_window_lower(bd->client.shell_win);
10878         else
10879           ecore_x_window_raise(bd->client.shell_win);
10880         bd->changes.shaded = 0;
10881         rem_change = 1;
10882      }
10883    else if (bd->changes.shaded)
10884      {
10885         if (bd->shaded)
10886           ecore_x_window_lower(bd->client.shell_win);
10887         else
10888           ecore_x_window_raise(bd->client.shell_win);
10889         bd->changes.size = 1;
10890         bd->changes.shaded = 0;
10891         rem_change = 1;
10892      }
10893
10894    if (bd->changes.size)
10895      {
10896         int x = 0, y = 0, xx = 0, yy = 0;
10897
10898         if ((bd->shaded) && (!bd->shading))
10899           {
10900              evas_obscured_clear(bd->bg_evas);
10901           }
10902         else
10903           {
10904              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
10905              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
10906
10907              evas_obscured_clear(bd->bg_evas);
10908              evas_obscured_rectangle_add(bd->bg_evas,
10909                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
10910
10911              if (bd->shading)
10912                {
10913                   if (bd->shade.dir == E_DIRECTION_UP)
10914                     {
10915                        y = yy - bd->client.h;
10916                     }
10917                   else if (bd->shade.dir == E_DIRECTION_LEFT)
10918                     {
10919                        x = xx - bd->client.w;
10920                     }
10921                }
10922           }
10923
10924         if (bd->client.e.state.video)
10925           {
10926              if (bd->client.e.state.video_position.updated)
10927                {
10928                   ecore_x_window_move(bd->win,
10929                                       bd->client.e.state.video_parent_border->x +
10930                                       bd->client.e.state.video_parent_border->client_inset.l +
10931                                       bd->client.e.state.video_parent_border->fx.x +
10932                                       bd->client.e.state.video_position.x,
10933                                       bd->client.e.state.video_parent_border->y +
10934                                       bd->client.e.state.video_parent_border->client_inset.t +
10935                                       bd->client.e.state.video_parent_border->fx.y +
10936                                       bd->client.e.state.video_position.y);
10937                   bd->client.e.state.video_position.updated = 0;
10938                }
10939           }
10940         else if (!bd->changes.pos)
10941           {
10942              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
10943              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
10944              bd->post_resize = 1;
10945           }
10946         else
10947           {
10948              E_Border *tmp;
10949              Eina_List *l;
10950
10951              ecore_x_window_move_resize(bd->win,
10952                                         bd->x + bd->fx.x,
10953                                         bd->y + bd->fx.y,
10954                                         bd->w, bd->h);
10955
10956              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
10957                ecore_x_window_move(tmp->win,
10958                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
10959                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
10960           }
10961
10962         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
10963
10964         if ((!bd->shaded) || (bd->shading))
10965           ecore_x_window_move_resize(bd->client.shell_win,
10966                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
10967
10968         if (bd->internal_ecore_evas)
10969           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
10970         else if (!bd->client.e.state.video)
10971           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
10972
10973         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
10974         evas_object_resize(bd->bg_object, bd->w, bd->h);
10975         e_container_shape_resize(bd->shape, bd->w, bd->h);
10976         if (bd->changes.pos)
10977           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
10978
10979         _e_border_client_move_resize_send(bd);
10980
10981         bd->changes.pos = 0;
10982         bd->changes.size = 0;
10983         rem_change = 1;
10984      }
10985    else if (bd->changes.pos)
10986      {
10987         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
10988         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
10989         bd->post_move = 1;
10990
10991         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
10992
10993         _e_border_client_move_resize_send(bd);
10994
10995         bd->changes.pos = 0;
10996         rem_change = 1;
10997      }
10998
10999    if (bd->changes.reset_gravity)
11000      {
11001         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
11002         bd->changes.reset_gravity = 0;
11003         rem_change = 1;
11004      }
11005
11006    if (bd->need_shape_merge)
11007      {
11008         _e_border_shape_input_rectangle_set(bd);
11009         if ((bd->shaped) || (bd->client.shaped))
11010           {
11011              Ecore_X_Window twin, twin2;
11012              int x, y;
11013
11014              twin = ecore_x_window_override_new
11015                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
11016              if (bd->shaped)
11017                ecore_x_window_shape_window_set(twin, bd->bg_win);
11018              else
11019                {
11020                   Ecore_X_Rectangle rects[4];
11021
11022                   rects[0].x = 0;
11023                   rects[0].y = 0;
11024                   rects[0].width = bd->w;
11025                   rects[0].height = bd->client_inset.t;
11026                   rects[1].x = 0;
11027                   rects[1].y = bd->client_inset.t;
11028                   rects[1].width = bd->client_inset.l;
11029                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11030                   rects[2].x = bd->w - bd->client_inset.r;
11031                   rects[2].y = bd->client_inset.t;
11032                   rects[2].width = bd->client_inset.r;
11033                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11034                   rects[3].x = 0;
11035                   rects[3].y = bd->h - bd->client_inset.b;
11036                   rects[3].width = bd->w;
11037                   rects[3].height = bd->client_inset.b;
11038                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
11039                }
11040              twin2 = ecore_x_window_override_new
11041                (bd->zone->container->scratch_win, 0, 0,
11042                 bd->w - bd->client_inset.l - bd->client_inset.r,
11043                 bd->h - bd->client_inset.t - bd->client_inset.b);
11044              x = 0;
11045              y = 0;
11046              if ((bd->shading) || (bd->shaded))
11047                {
11048                   if (bd->shade.dir == E_DIRECTION_UP)
11049                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
11050                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11051                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
11052                }
11053              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
11054                                                 x, y);
11055              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
11056                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
11057                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
11058              ecore_x_window_shape_window_add_xy(twin, twin2,
11059                                                 bd->client_inset.l,
11060                                                 bd->client_inset.t);
11061              ecore_x_window_free(twin2);
11062              ecore_x_window_shape_window_set(bd->win, twin);
11063              ecore_x_window_free(twin);
11064           }
11065         else
11066           ecore_x_window_shape_mask_set(bd->win, 0);
11067         //      bd->need_shape_export = 1;
11068         bd->need_shape_merge = 0;
11069      }
11070
11071    if (bd->need_shape_export)
11072      {
11073         Ecore_X_Rectangle *rects, *orects;
11074         int num;
11075
11076         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
11077         if (rects)
11078           {
11079              int changed;
11080
11081              changed = 1;
11082              if ((num == bd->shape_rects_num) && (bd->shape_rects))
11083                {
11084                   int i;
11085
11086                   orects = bd->shape_rects;
11087                   changed = 0;
11088                   for (i = 0; i < num; i++)
11089                     {
11090                        if (rects[i].x < 0)
11091                          {
11092                             rects[i].width -= rects[i].x;
11093                             rects[i].x = 0;
11094                          }
11095                        if ((rects[i].x + (int)rects[i].width) > bd->w)
11096                          rects[i].width = rects[i].width - rects[i].x;
11097                        if (rects[i].y < 0)
11098                          {
11099                             rects[i].height -= rects[i].y;
11100                             rects[i].y = 0;
11101                          }
11102                        if ((rects[i].y + (int)rects[i].height) > bd->h)
11103                          rects[i].height = rects[i].height - rects[i].y;
11104
11105                        if ((orects[i].x != rects[i].x) ||
11106                            (orects[i].y != rects[i].y) ||
11107                            (orects[i].width != rects[i].width) ||
11108                            (orects[i].height != rects[i].height))
11109                          {
11110                             changed = 1;
11111                             break;
11112                          }
11113                     }
11114                }
11115              if (changed)
11116                {
11117                   if (bd->client.shaped)
11118                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
11119                   else
11120                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
11121                   E_FREE(bd->shape_rects);
11122                   bd->shape_rects = rects;
11123                   bd->shape_rects_num = num;
11124                   e_container_shape_rects_set(bd->shape, rects, num);
11125                }
11126              else
11127                free(rects);
11128           }
11129         else
11130           {
11131              E_FREE(bd->shape_rects);
11132              bd->shape_rects = NULL;
11133              bd->shape_rects_num = 0;
11134              e_container_shape_rects_set(bd->shape, NULL, 0);
11135           }
11136         bd->need_shape_export = 0;
11137      }
11138
11139    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
11140      {
11141         int x, y;
11142
11143         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
11144         if ((!bd->placed) && (!bd->re_manage) &&
11145             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
11146             (!((bd->client.icccm.transient_for != 0) ||
11147                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
11148             (!bdmove) && (!bdresize))
11149           {
11150              /* Set this window into moving state */
11151
11152              bd->cur_mouse_action = e_action_find("window_move");
11153              if (bd->cur_mouse_action)
11154                {
11155                   if ((!bd->cur_mouse_action->func.end_mouse) &&
11156                       (!bd->cur_mouse_action->func.end))
11157                     bd->cur_mouse_action = NULL;
11158                   if (bd->cur_mouse_action)
11159                     {
11160                        bd->x = x - (bd->w >> 1);
11161                        bd->y = y - (bd->client_inset.t >> 1);
11162                        bd->changed = 1;
11163                        bd->changes.pos = 1;
11164
11165                        _e_border_client_move_resize_send(bd);
11166                     }
11167                }
11168           }
11169
11170         _e_border_show(bd);
11171
11172         if (bd->cur_mouse_action)
11173           {
11174              bd->moveinfo.down.x = bd->x + bd->fx.x;
11175              bd->moveinfo.down.y = bd->y + bd->fx.y;
11176              bd->moveinfo.down.w = bd->w;
11177              bd->moveinfo.down.h = bd->h;
11178              bd->mouse.current.mx = x;
11179              bd->mouse.current.my = y;
11180              bd->moveinfo.down.button = 0;
11181              bd->moveinfo.down.mx = x;
11182              bd->moveinfo.down.my = y;
11183
11184              grabbed = 1;
11185              e_object_ref(E_OBJECT(bd->cur_mouse_action));
11186              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
11187              if (e_config->border_raise_on_mouse_action)
11188                e_border_raise(bd);
11189              e_border_focus_set(bd, 1, 1);
11190           }
11191         bd->changes.visible = 0;
11192         rem_change = 1;
11193      }
11194
11195    if (bd->changes.icon)
11196      {
11197         if (bd->desktop)
11198           {
11199              efreet_desktop_free(bd->desktop);
11200              bd->desktop = NULL;
11201           }
11202         if (bd->icon_object)
11203           {
11204              evas_object_del(bd->icon_object);
11205              bd->icon_object = NULL;
11206           }
11207         if (bd->remember && bd->remember->prop.desktop_file)
11208           {
11209              const char *desktop = bd->remember->prop.desktop_file;
11210
11211              bd->desktop = efreet_desktop_get(desktop);
11212              if (!bd->desktop)
11213                bd->desktop = efreet_util_desktop_name_find(desktop);
11214           }
11215         if (!bd->desktop)
11216           {
11217              if ((bd->client.icccm.name) && (bd->client.icccm.class))
11218                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
11219                                                                bd->client.icccm.class);
11220           }
11221         if (!bd->desktop)
11222           {
11223              /* libreoffice and maybe others match window class
11224                 with .desktop file name */
11225              if (bd->client.icccm.class)
11226                {
11227                   char buf[128];
11228                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
11229                   bd->desktop = efreet_util_desktop_file_id_find(buf);
11230                }
11231           }
11232         if (!bd->desktop)
11233           {
11234              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
11235                                                       bd->client.netwm.pid);
11236              if (bd->desktop) efreet_desktop_ref(bd->desktop);
11237           }
11238         if (!bd->desktop && bd->client.icccm.name)
11239           {
11240              /* this works for most cases as fallback. useful when app is
11241                 run from a shell  */
11242              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
11243           }
11244         if (!bd->desktop && bd->client.icccm.transient_for)
11245           {
11246              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
11247              if (bd2 && bd2->desktop)
11248                {
11249                   efreet_desktop_ref(bd2->desktop);
11250                   bd->desktop = bd2->desktop;
11251                }
11252           }
11253         if (bd->desktop)
11254           {
11255              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
11256                                             bd->desktop->orig_path);
11257           }
11258
11259         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
11260         if ((bd->focused) && (bd->icon_object))
11261           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
11262         if (bd->bg_object)
11263           {
11264              evas_object_show(bd->icon_object);
11265              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
11266           }
11267         else
11268           evas_object_hide(bd->icon_object);
11269
11270         {
11271            E_Event_Border_Icon_Change *ev;
11272
11273            ev = E_NEW(E_Event_Border_Icon_Change, 1);
11274            ev->border = bd;
11275            e_object_ref(E_OBJECT(bd));
11276            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
11277            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
11278                            _e_border_event_border_icon_change_free, NULL);
11279         }
11280         bd->changes.icon = 0;
11281      }
11282
11283    bd->new_client = 0;
11284    bd->changed = 0;
11285    bd->changes.stack = 0;
11286    bd->changes.prop = 0;
11287
11288    if ((bd->take_focus) || (bd->want_focus))
11289      {
11290         bd->take_focus = 0;
11291 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11292         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
11293             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
11294             (bd->want_focus))
11295 #else // original
11296         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
11297 #endif
11298           {
11299              bd->want_focus = 0;
11300 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11301              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
11302                 _e_border_check_stack(bd);
11303              else
11304 #endif
11305              e_border_focus_set_with_pointer(bd);
11306           }
11307         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11308           {
11309              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
11310                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
11311                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
11312                    e_border_focused_get())))
11313                {
11314                   e_border_focus_set_with_pointer(bd);
11315                }
11316           }
11317         else
11318           {
11319              /* focus window by default when it is the only one on desk */
11320              E_Border *bd2 = NULL;
11321              Eina_List *l;
11322              EINA_LIST_FOREACH(focus_stack, l, bd2)
11323                {
11324                   if (bd == bd2) continue;
11325                   if ((!bd2->iconic) && (bd2->visible) &&
11326                       ((bd->desk == bd2->desk) || bd2->sticky))
11327                     break;
11328                }
11329
11330              if (!bd2)
11331                {
11332                   e_border_focus_set_with_pointer(bd);
11333                }
11334           }
11335      }
11336
11337    if (bd->need_maximize)
11338      {
11339         E_Maximize max;
11340         max = bd->maximized;
11341         bd->maximized = E_MAXIMIZE_NONE;
11342         e_border_maximize(bd, max);
11343         bd->need_maximize = 0;
11344      }
11345
11346    if (bd->need_fullscreen)
11347      {
11348         e_border_fullscreen(bd, e_config->fullscreen_policy);
11349         bd->need_fullscreen = 0;
11350      }
11351
11352    if (rem_change)
11353      e_remember_update(bd);
11354
11355    if (send_event) // FIXME: send only if a property changed - above need to
11356      { // check on that. for now - always send.
11357         event = E_NEW(E_Event_Border_Property, 1);
11358         event->border = bd;
11359         e_object_ref(E_OBJECT(bd));
11360         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11361      }
11362    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11363 }
11364
11365 static void
11366 _e_border_moveinfo_gather(E_Border   *bd,
11367                           const char *source)
11368 {
11369    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11370    else if (e_util_glob_match(source, "mouse,*,2"))
11371      bd->moveinfo.down.button = 2;
11372    else if (e_util_glob_match(source, "mouse,*,3"))
11373      bd->moveinfo.down.button = 3;
11374    else bd->moveinfo.down.button = 0;
11375    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11376      {
11377         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11378         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11379      }
11380    else
11381      {
11382         bd->moveinfo.down.mx = bd->mouse.current.mx;
11383         bd->moveinfo.down.my = bd->mouse.current.my;
11384      }
11385 }
11386
11387 static void
11388 _e_border_resize_handle(E_Border *bd)
11389 {
11390    int x, y, w, h;
11391    int new_x, new_y, new_w, new_h;
11392    int tw, th;
11393    Eina_List *skiplist = NULL;
11394
11395    x = bd->x;
11396    y = bd->y;
11397    w = bd->w;
11398    h = bd->h;
11399
11400    if ((bd->resize_mode == RESIZE_TR) ||
11401        (bd->resize_mode == RESIZE_R) ||
11402        (bd->resize_mode == RESIZE_BR))
11403      {
11404         if ((bd->moveinfo.down.button >= 1) &&
11405             (bd->moveinfo.down.button <= 3))
11406           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11407             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11408         else
11409           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11410      }
11411    else if ((bd->resize_mode == RESIZE_TL) ||
11412             (bd->resize_mode == RESIZE_L) ||
11413             (bd->resize_mode == RESIZE_BL))
11414      {
11415         if ((bd->moveinfo.down.button >= 1) &&
11416             (bd->moveinfo.down.button <= 3))
11417           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11418             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11419         else
11420           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11421      }
11422
11423    if ((bd->resize_mode == RESIZE_TL) ||
11424        (bd->resize_mode == RESIZE_T) ||
11425        (bd->resize_mode == RESIZE_TR))
11426      {
11427         if ((bd->moveinfo.down.button >= 1) &&
11428             (bd->moveinfo.down.button <= 3))
11429           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11430             (bd->mouse.current.my - bd->moveinfo.down.my);
11431         else
11432           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11433      }
11434    else if ((bd->resize_mode == RESIZE_BL) ||
11435             (bd->resize_mode == RESIZE_B) ||
11436             (bd->resize_mode == RESIZE_BR))
11437      {
11438         if ((bd->moveinfo.down.button >= 1) &&
11439             (bd->moveinfo.down.button <= 3))
11440           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11441             (bd->mouse.current.my - bd->moveinfo.down.my);
11442         else
11443           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11444      }
11445
11446    tw = bd->w;
11447    th = bd->h;
11448
11449    if ((bd->resize_mode == RESIZE_TL) ||
11450        (bd->resize_mode == RESIZE_L) ||
11451        (bd->resize_mode == RESIZE_BL))
11452      x += (tw - w);
11453    if ((bd->resize_mode == RESIZE_TL) ||
11454        (bd->resize_mode == RESIZE_T) ||
11455        (bd->resize_mode == RESIZE_TR))
11456      y += (th - h);
11457
11458    skiplist = eina_list_append(skiplist, bd);
11459    e_resist_container_border_position(bd->zone->container, skiplist,
11460                                       bd->x, bd->y, bd->w, bd->h,
11461                                       x, y, w, h,
11462                                       &new_x, &new_y, &new_w, &new_h);
11463    eina_list_free(skiplist);
11464
11465    w = new_w;
11466    h = new_h;
11467    e_border_resize_limit(bd, &new_w, &new_h);
11468    if ((bd->resize_mode == RESIZE_TL) ||
11469        (bd->resize_mode == RESIZE_L) ||
11470        (bd->resize_mode == RESIZE_BL))
11471      new_x += (w - new_w);
11472    if ((bd->resize_mode == RESIZE_TL) ||
11473        (bd->resize_mode == RESIZE_T) ||
11474        (bd->resize_mode == RESIZE_TR))
11475      new_y += (h - new_h);
11476
11477    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11478 }
11479
11480 static Eina_Bool
11481 _e_border_shade_animator(void *data)
11482 {
11483    E_Border *bd = data;
11484    double dt, val;
11485    double dur = bd->client.h / e_config->border_shade_speed;
11486
11487    dt = ecore_loop_time_get() - bd->shade.start;
11488    val = dt / dur;
11489
11490    if (val < 0.0) val = 0.0;
11491    else if (val > 1.0) val = 1.0;
11492
11493    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11494      {
11495         bd->shade.val =
11496            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
11497         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11498      }
11499    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
11500      {
11501         bd->shade.val =
11502            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
11503         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11504      }
11505    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
11506      {
11507         bd->shade.val =
11508            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
11509         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11510      }
11511    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
11512      {
11513         bd->shade.val =
11514            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11515         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11516      }
11517    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
11518      {
11519         bd->shade.val =
11520            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
11521         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11522      }
11523    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
11524      {
11525         bd->shade.val =
11526            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
11527         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11528      }
11529    else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
11530      {
11531         bd->shade.val =
11532            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.0);
11533         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11534      }
11535    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE)
11536      {
11537         bd->shade.val =
11538            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
11539         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11540      }
11541    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
11542      {
11543         bd->shade.val =
11544            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
11545         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11546      }
11547    else
11548      {
11549         bd->shade.val =
11550            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11551         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11552      }
11553
11554    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
11555    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
11556    else if (bd->shade.val > .999)
11557      bd->shade.val = 1.0;
11558
11559    if (bd->shade.dir == E_DIRECTION_UP)
11560      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11561    else if (bd->shade.dir == E_DIRECTION_DOWN)
11562      {
11563         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11564         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
11565         bd->changes.pos = 1;
11566      }
11567    else if (bd->shade.dir == E_DIRECTION_LEFT)
11568      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11569    else if (bd->shade.dir == E_DIRECTION_RIGHT)
11570      {
11571         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11572         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
11573         bd->changes.pos = 1;
11574      }
11575
11576    if ((bd->shaped) || (bd->client.shaped))
11577      {
11578         bd->need_shape_merge = 1;
11579         bd->need_shape_export = 1;
11580      }
11581    if (bd->shaped_input)
11582      {
11583         bd->need_shape_merge = 1;
11584      }
11585    bd->changes.size = 1;
11586    bd->changed = 1;
11587
11588    /* we're done */
11589    if (val == 1)
11590      {
11591         E_Event_Border_Resize *ev;
11592
11593         bd->shading = 0;
11594         bd->shaded = !(bd->shaded);
11595         bd->changes.size = 1;
11596         bd->changes.shaded = 1;
11597         bd->changes.shading = 1;
11598         bd->changed = 1;
11599         bd->shade.anim = NULL;
11600
11601         if (bd->shaded)
11602           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
11603         else
11604           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
11605         edje_object_message_signal_process(bd->bg_object);
11606         e_border_frame_recalc(bd);
11607
11608         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
11609         ev = E_NEW(E_Event_Border_Resize, 1);
11610         ev->border = bd;
11611         e_object_ref(E_OBJECT(bd));
11612 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
11613         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
11614         return ECORE_CALLBACK_CANCEL;
11615      }
11616    return ECORE_CALLBACK_RENEW;
11617 }
11618
11619 static void
11620 _e_border_event_border_resize_free(void *data __UNUSED__,
11621                                    void      *ev)
11622 {
11623    E_Event_Border_Resize *e;
11624
11625    e = ev;
11626 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
11627    e_object_unref(E_OBJECT(e->border));
11628    E_FREE(e);
11629 }
11630
11631 static void
11632 _e_border_event_border_move_free(void *data __UNUSED__,
11633                                  void      *ev)
11634 {
11635    E_Event_Border_Move *e;
11636
11637    e = ev;
11638 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
11639    e_object_unref(E_OBJECT(e->border));
11640    E_FREE(e);
11641 }
11642
11643 static void
11644 _e_border_event_border_add_free(void *data __UNUSED__,
11645                                 void      *ev)
11646 {
11647    E_Event_Border_Add *e;
11648
11649    e = ev;
11650 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
11651    e_object_unref(E_OBJECT(e->border));
11652    E_FREE(e);
11653 }
11654
11655 static void
11656 _e_border_event_border_remove_free(void *data __UNUSED__,
11657                                    void      *ev)
11658 {
11659    E_Event_Border_Remove *e;
11660
11661    e = ev;
11662 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
11663    e_object_unref(E_OBJECT(e->border));
11664    E_FREE(e);
11665 }
11666
11667 static void
11668 _e_border_event_border_show_free(void *data __UNUSED__,
11669                                  void      *ev)
11670 {
11671    E_Event_Border_Show *e;
11672
11673    e = ev;
11674 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
11675    e_object_unref(E_OBJECT(e->border));
11676    E_FREE(e);
11677 }
11678
11679 static void
11680 _e_border_event_border_hide_free(void *data __UNUSED__,
11681                                  void      *ev)
11682 {
11683    E_Event_Border_Hide *e;
11684
11685    e = ev;
11686 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
11687    e_object_unref(E_OBJECT(e->border));
11688    E_FREE(e);
11689 }
11690
11691 static void
11692 _e_border_event_border_iconify_free(void *data __UNUSED__,
11693                                     void      *ev)
11694 {
11695    E_Event_Border_Iconify *e;
11696
11697    e = ev;
11698 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
11699    e_object_unref(E_OBJECT(e->border));
11700    E_FREE(e);
11701 }
11702
11703 static void
11704 _e_border_event_border_uniconify_free(void *data __UNUSED__,
11705                                       void      *ev)
11706 {
11707    E_Event_Border_Uniconify *e;
11708
11709    e = ev;
11710 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
11711    e_object_unref(E_OBJECT(e->border));
11712    E_FREE(e);
11713 }
11714
11715 static void
11716 _e_border_event_border_stick_free(void *data __UNUSED__,
11717                                   void      *ev)
11718 {
11719    E_Event_Border_Stick *e;
11720
11721    e = ev;
11722 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
11723    e_object_unref(E_OBJECT(e->border));
11724    E_FREE(e);
11725 }
11726
11727 static void
11728 _e_border_event_border_unstick_free(void *data __UNUSED__,
11729                                     void      *ev)
11730 {
11731    E_Event_Border_Unstick *e;
11732
11733    e = ev;
11734 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
11735    e_object_unref(E_OBJECT(e->border));
11736    E_FREE(e);
11737 }
11738
11739 static void
11740 _e_border_event_border_zone_set_free(void *data __UNUSED__,
11741                                      void      *ev)
11742 {
11743    E_Event_Border_Zone_Set *e;
11744
11745    e = ev;
11746 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
11747    e_object_unref(E_OBJECT(e->border));
11748    e_object_unref(E_OBJECT(e->zone));
11749    E_FREE(e);
11750 }
11751
11752 static void
11753 _e_border_event_border_desk_set_free(void *data __UNUSED__,
11754                                      void      *ev)
11755 {
11756    E_Event_Border_Desk_Set *e;
11757
11758    e = ev;
11759 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
11760    e_object_unref(E_OBJECT(e->border));
11761    e_object_unref(E_OBJECT(e->desk));
11762    E_FREE(e);
11763 }
11764
11765 static void
11766 _e_border_event_border_stack_free(void *data __UNUSED__,
11767                                   void      *ev)
11768 {
11769    E_Event_Border_Stack *e;
11770
11771    e = ev;
11772 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
11773    e_object_unref(E_OBJECT(e->border));
11774    if (e->stack)
11775      {
11776 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
11777           e_object_unref(E_OBJECT(e->stack));
11778      }
11779    E_FREE(e);
11780 }
11781
11782 static void
11783 _e_border_event_border_icon_change_free(void *data __UNUSED__,
11784                                         void      *ev)
11785 {
11786    E_Event_Border_Icon_Change *e;
11787
11788    e = ev;
11789 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
11790    e_object_unref(E_OBJECT(e->border));
11791    E_FREE(e);
11792 }
11793
11794 static void
11795 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
11796                                           void      *ev)
11797 {
11798    E_Event_Border_Urgent_Change *e;
11799
11800    e = ev;
11801    e_object_unref(E_OBJECT(e->border));
11802    E_FREE(e);
11803 }
11804
11805 static void
11806 _e_border_event_border_focus_in_free(void *data __UNUSED__,
11807                                      void      *ev)
11808 {
11809    E_Event_Border_Focus_In *e;
11810
11811    e = ev;
11812    e_object_unref(E_OBJECT(e->border));
11813    E_FREE(e);
11814 }
11815
11816 static void
11817 _e_border_event_border_focus_out_free(void *data __UNUSED__,
11818                                       void      *ev)
11819 {
11820    E_Event_Border_Focus_Out *e;
11821
11822    e = ev;
11823    e_object_unref(E_OBJECT(e->border));
11824    E_FREE(e);
11825 }
11826
11827 static void
11828 _e_border_event_border_property_free(void *data __UNUSED__,
11829                                      void      *ev)
11830 {
11831    E_Event_Border_Property *e;
11832
11833    e = ev;
11834    e_object_unref(E_OBJECT(e->border));
11835    E_FREE(e);
11836 }
11837
11838 static void
11839 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
11840                                        void      *ev)
11841 {
11842    E_Event_Border_Fullscreen *e;
11843
11844    e = ev;
11845 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
11846    e_object_unref(E_OBJECT(e->border));
11847    E_FREE(e);
11848 }
11849
11850 static void
11851 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
11852                                          void      *ev)
11853 {
11854    E_Event_Border_Unfullscreen *e;
11855
11856    e = ev;
11857 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
11858    e_object_unref(E_OBJECT(e->border));
11859    E_FREE(e);
11860 }
11861
11862 #ifdef _F_ZONE_WINDOW_ROTATION_
11863 static void
11864 _e_border_event_border_rotation_change_begin_free(void *data __UNUSED__,
11865                                                   void      *ev)
11866 {
11867    E_Event_Border_Rotation_Change_Begin *e;
11868    e = ev;
11869    e_object_unref(E_OBJECT(e->border));
11870    E_FREE(e);
11871 }
11872
11873 static void
11874 _e_border_event_border_rotation_change_cancel_free(void *data __UNUSED__,
11875                                                    void      *ev)
11876 {
11877    E_Event_Border_Rotation_Change_Cancel *e;
11878    e = ev;
11879    e_object_unref(E_OBJECT(e->border));
11880    E_FREE(e);
11881 }
11882
11883 static void
11884 _e_border_event_border_rotation_change_end_free(void *data __UNUSED__,
11885                                                 void      *ev)
11886 {
11887    E_Event_Border_Rotation_Change_End *e;
11888    e = ev;
11889    e_object_unref(E_OBJECT(e->border));
11890    E_FREE(e);
11891 }
11892
11893 static void
11894 _e_border_event_border_rotation_change_begin_send(E_Border *bd)
11895 {
11896    E_Event_Border_Rotation_Change_Begin *ev = NULL;
11897    ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
11898    if (ev)
11899      {
11900         ev->border = bd;
11901         e_object_ref(E_OBJECT(bd));
11902         ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_BEGIN,
11903                         ev,
11904                         _e_border_event_border_rotation_change_begin_free,
11905                         NULL);
11906      }
11907 }
11908 #endif
11909
11910 static void
11911 _e_border_zone_update(E_Border *bd)
11912 {
11913    E_Container *con;
11914    Eina_List *l;
11915    E_Zone *zone;
11916
11917    /* still within old zone - leave it there */
11918    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
11919                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
11920 #if _F_BORDER_CLIP_TO_ZONE_
11921      {
11922         _e_border_shape_input_clip_to_zone(bd);
11923         return;
11924      }
11925 #else
11926      return;
11927 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
11928    /* find a new zone */
11929    con = bd->zone->container;
11930    EINA_LIST_FOREACH(con->zones, l, zone)
11931      {
11932         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
11933                          zone->x, zone->y, zone->w, zone->h))
11934           {
11935              e_border_zone_set(bd, zone);
11936 #if _F_BORDER_CLIP_TO_ZONE_
11937              _e_border_shape_input_clip_to_zone(bd);
11938 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
11939              return;
11940           }
11941      }
11942 }
11943
11944 static int
11945 _e_border_resize_begin(E_Border *bd)
11946 {
11947    if (!bd->lock_user_stacking)
11948      {
11949         if (e_config->border_raise_on_mouse_action)
11950           e_border_raise(bd);
11951      }
11952    if ((bd->shaded) || (bd->shading) ||
11953        (bd->fullscreen) || (bd->lock_user_size))
11954      return 0;
11955
11956    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
11957      {
11958         grabbed = 0;
11959         return 0;
11960      }
11961
11962    if (bd->client.netwm.sync.request)
11963      {
11964         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
11965         bd->client.netwm.sync.serial = 1;
11966         bd->client.netwm.sync.wait = 0;
11967         bd->client.netwm.sync.send_time = ecore_loop_time_get();
11968      }
11969
11970    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
11971
11972    bdresize = bd;
11973    return 1;
11974 }
11975
11976 static int
11977 _e_border_resize_end(E_Border *bd)
11978 {
11979    if (grabbed)
11980      {
11981         e_grabinput_release(bd->win, bd->win);
11982         grabbed = 0;
11983      }
11984    if (bd->client.netwm.sync.alarm)
11985      {
11986         E_Border_Pending_Move_Resize *pnd;
11987
11988         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
11989         bd->client.netwm.sync.alarm = 0;
11990         /* resize to last geometry if sync alarm for it was not yet handled */
11991         if (bd->pending_move_resize)
11992           {
11993              bd->changed = 1;
11994              bd->changes.pos = 1;
11995              bd->changes.size = 1;
11996              _e_border_client_move_resize_send(bd);
11997           }
11998
11999         EINA_LIST_FREE(bd->pending_move_resize, pnd)
12000           E_FREE(pnd);
12001      }
12002
12003    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
12004
12005    bdresize = NULL;
12006
12007    /* If this border was maximized, we need to unset Maximized state or
12008     * on restart, E still thinks it's maximized */
12009    if (bd->maximized != E_MAXIMIZE_NONE)
12010      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
12011                                   bd->maximized & E_MAXIMIZE_NONE);
12012    return 1;
12013 }
12014
12015 static void
12016 _e_border_resize_update(E_Border *bd)
12017 {
12018    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
12019 }
12020
12021 static int
12022 _e_border_move_begin(E_Border *bd)
12023 {
12024    if (!bd->lock_user_stacking)
12025      {
12026         if (e_config->border_raise_on_mouse_action)
12027           e_border_raise(bd);
12028      }
12029    if ((bd->fullscreen) || (bd->lock_user_location))
12030      return 0;
12031
12032    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
12033      {
12034         grabbed = 0;
12035         return 0;
12036      }
12037 #if 0
12038    if (bd->client.netwm.sync.request)
12039      {
12040         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12041         bd->client.netwm.sync.serial = 0;
12042         bd->client.netwm.sync.wait = 0;
12043         bd->client.netwm.sync.time = ecore_loop_time_get();
12044      }
12045 #endif
12046    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
12047
12048    bdmove = bd;
12049    return 1;
12050 }
12051
12052 static int
12053 _e_border_move_end(E_Border *bd)
12054 {
12055    if (grabbed)
12056      {
12057         e_grabinput_release(bd->win, bd->win);
12058         grabbed = 0;
12059      }
12060 #if 0
12061    if (bd->client.netwm.sync.alarm)
12062      {
12063         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12064         bd->client.netwm.sync.alarm = 0;
12065      }
12066 #endif
12067    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
12068
12069    bdmove = NULL;
12070    return 1;
12071 }
12072
12073 static void
12074 _e_border_move_update(E_Border *bd)
12075 {
12076    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
12077 }
12078
12079 static Eina_Bool
12080 _e_border_cb_ping_poller(void *data)
12081 {
12082    E_Border *bd;
12083
12084    bd = data;
12085    if (bd->ping_ok)
12086      {
12087         if (bd->hung)
12088           {
12089              bd->hung = 0;
12090              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
12091              if (bd->kill_timer)
12092                {
12093                   ecore_timer_del(bd->kill_timer);
12094                   bd->kill_timer = NULL;
12095                }
12096           }
12097      }
12098    else
12099      {
12100         /* if time between last ping and now is greater
12101          * than half the ping interval... */
12102         if ((ecore_loop_time_get() - bd->ping) >
12103             ((e_config->ping_clients_interval *
12104               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
12105           {
12106              if (!bd->hung)
12107                {
12108                   bd->hung = 1;
12109                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
12110                   /* FIXME: if below dialog is up - hide it now */
12111                }
12112              if (bd->delete_requested)
12113                {
12114                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
12115                   e_border_act_kill_begin(bd);
12116                }
12117           }
12118      }
12119    bd->ping_poller = NULL;
12120    e_border_ping(bd);
12121    return ECORE_CALLBACK_CANCEL;
12122 }
12123
12124 static Eina_Bool
12125 _e_border_cb_kill_timer(void *data)
12126 {
12127    E_Border *bd;
12128
12129    bd = data;
12130 // dont wait until it's hung -
12131 //   if (bd->hung)
12132 //     {
12133         if (bd->client.netwm.pid > 1)
12134           kill(bd->client.netwm.pid, SIGKILL);
12135 //     }
12136    bd->kill_timer = NULL;
12137    return ECORE_CALLBACK_CANCEL;
12138 }
12139
12140 static void
12141 _e_border_pointer_resize_begin(E_Border *bd)
12142 {
12143    switch (bd->resize_mode)
12144      {
12145       case RESIZE_TL:
12146         e_pointer_type_push(bd->pointer, bd, "resize_tl");
12147         break;
12148
12149       case RESIZE_T:
12150         e_pointer_type_push(bd->pointer, bd, "resize_t");
12151         break;
12152
12153       case RESIZE_TR:
12154         e_pointer_type_push(bd->pointer, bd, "resize_tr");
12155         break;
12156
12157       case RESIZE_R:
12158         e_pointer_type_push(bd->pointer, bd, "resize_r");
12159         break;
12160
12161       case RESIZE_BR:
12162         e_pointer_type_push(bd->pointer, bd, "resize_br");
12163         break;
12164
12165       case RESIZE_B:
12166         e_pointer_type_push(bd->pointer, bd, "resize_b");
12167         break;
12168
12169       case RESIZE_BL:
12170         e_pointer_type_push(bd->pointer, bd, "resize_bl");
12171         break;
12172
12173       case RESIZE_L:
12174         e_pointer_type_push(bd->pointer, bd, "resize_l");
12175         break;
12176      }
12177 }
12178
12179 static void
12180 _e_border_pointer_resize_end(E_Border *bd)
12181 {
12182    switch (bd->resize_mode)
12183      {
12184       case RESIZE_TL:
12185         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
12186         break;
12187
12188       case RESIZE_T:
12189         e_pointer_type_pop(bd->pointer, bd, "resize_t");
12190         break;
12191
12192       case RESIZE_TR:
12193         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
12194         break;
12195
12196       case RESIZE_R:
12197         e_pointer_type_pop(bd->pointer, bd, "resize_r");
12198         break;
12199
12200       case RESIZE_BR:
12201         e_pointer_type_pop(bd->pointer, bd, "resize_br");
12202         break;
12203
12204       case RESIZE_B:
12205         e_pointer_type_pop(bd->pointer, bd, "resize_b");
12206         break;
12207
12208       case RESIZE_BL:
12209         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
12210         break;
12211
12212       case RESIZE_L:
12213         e_pointer_type_pop(bd->pointer, bd, "resize_l");
12214         break;
12215      }
12216 }
12217
12218 static void
12219 _e_border_pointer_move_begin(E_Border *bd)
12220 {
12221    e_pointer_type_push(bd->pointer, bd, "move");
12222 }
12223
12224 static void
12225 _e_border_pointer_move_end(E_Border *bd)
12226 {
12227    e_pointer_type_pop(bd->pointer, bd, "move");
12228 }
12229
12230 static Eina_List *_e_border_hooks = NULL;
12231 static int _e_border_hooks_delete = 0;
12232 static int _e_border_hooks_walking = 0;
12233
12234 static void
12235 _e_border_hooks_clean(void)
12236 {
12237    Eina_List *l, *ln;
12238    E_Border_Hook *bh;
12239
12240    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
12241      {
12242         if (bh->delete_me)
12243           {
12244              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
12245              free(bh);
12246           }
12247      }
12248 }
12249
12250 static void
12251 _e_border_hook_call(E_Border_Hook_Point hookpoint,
12252                     void               *bd)
12253 {
12254    Eina_List *l;
12255    E_Border_Hook *bh;
12256
12257    _e_border_hooks_walking++;
12258    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
12259      {
12260         if (bh->delete_me) continue;
12261         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
12262      }
12263    _e_border_hooks_walking--;
12264    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
12265      _e_border_hooks_clean();
12266 }
12267
12268 EAPI E_Border_Hook *
12269 e_border_hook_add(E_Border_Hook_Point               hookpoint,
12270                   void                              (*func)(void *data,
12271                                               void *bd),
12272                   void                             *data)
12273 {
12274    E_Border_Hook *bh;
12275
12276    bh = E_NEW(E_Border_Hook, 1);
12277    if (!bh) return NULL;
12278    bh->hookpoint = hookpoint;
12279    bh->func = func;
12280    bh->data = data;
12281    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
12282    return bh;
12283 }
12284
12285 EAPI void
12286 e_border_hook_del(E_Border_Hook *bh)
12287 {
12288    bh->delete_me = 1;
12289    if (_e_border_hooks_walking == 0)
12290      {
12291         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
12292         free(bh);
12293      }
12294    else
12295      _e_border_hooks_delete++;
12296 }
12297
12298 EAPI void
12299 e_border_focus_track_freeze(void)
12300 {
12301    focus_track_frozen++;
12302 }
12303
12304 EAPI void
12305 e_border_focus_track_thaw(void)
12306 {
12307    focus_track_frozen--;
12308 }
12309
12310 EAPI E_Border *
12311 e_border_under_pointer_get(E_Desk   *desk,
12312                            E_Border *exclude)
12313 {
12314    E_Border *bd = NULL, *cbd;
12315    Eina_List *l;
12316    int x, y;
12317
12318    /* We need to ensure that we can get the container window for the
12319     * zone of either the given desk or the desk of the excluded
12320     * window, so return if neither is given */
12321    if (desk)
12322      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
12323    else if (exclude)
12324      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
12325    else
12326      return NULL;
12327
12328    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
12329      {
12330         if (!cbd) continue;
12331         /* If a border was specified which should be excluded from the list
12332          * (because it will be closed shortly for example), skip */
12333         if ((exclude) && (cbd == exclude)) continue;
12334         if ((desk) && (cbd->desk != desk)) continue;
12335         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
12336           continue;
12337         /* If the layer is higher, the position of the window is higher
12338          * (always on top vs always below) */
12339         if (!bd || (cbd->layer > bd->layer))
12340           {
12341              bd = cbd;
12342              break;
12343           }
12344      }
12345    return bd;
12346 }
12347
12348 static Eina_Bool
12349 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
12350 {
12351    if (warp_to)
12352      {
12353         int x, y;
12354         double spd;
12355
12356         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
12357         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
12358             (y - warp_y) > 5 || (y - warp_y) < -5)
12359           {
12360              /* User moved the mouse, so stop warping */
12361              warp_to = 0;
12362              goto cleanup;
12363           }
12364
12365         /* We just use the same warp speed as configured
12366          * for the windowlist */
12367         spd = e_config->winlist_warp_speed;
12368         x = warp_x;
12369         y = warp_y;
12370         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12371         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12372         if (warp_x == x && warp_y == y)
12373           {
12374              warp_x = warp_to_x;
12375              warp_y = warp_to_y;
12376              warp_to = 0;
12377              goto cleanup;
12378           }
12379         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12380         return ECORE_CALLBACK_RENEW;
12381      }
12382  cleanup:
12383    ecore_timer_del(warp_timer);
12384    warp_timer = NULL;
12385    return ECORE_CALLBACK_CANCEL;
12386 }
12387
12388 EAPI int
12389 e_border_pointer_warp_to_center(E_Border *bd)
12390 {
12391    int x, y;
12392
12393    /* Do not slide pointer when disabled (probably breaks focus
12394     * on sloppy/mouse focus but requested by users). */
12395    if (!e_config->pointer_slide) return 0;
12396    /* Only warp the pointer if it is not already in the area of
12397     * the given border */
12398    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12399    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12400        (y >= bd->y) && (y <= (bd->y + bd->h)))
12401      return 0;
12402
12403    warp_to_x = bd->x + (bd->w / 2);
12404    if (warp_to_x < (bd->zone->x + 1))
12405      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12406    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12407      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12408
12409    warp_to_y = bd->y + (bd->h / 2);
12410    if (warp_to_y < (bd->zone->y + 1))
12411      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12412    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12413      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12414
12415    warp_to = 1;
12416    warp_to_win = bd->zone->container->win;
12417    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12418    if (!warp_timer)
12419      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12420    return 1;
12421 }
12422
12423 EAPI void
12424 e_border_comp_hidden_set(E_Border *bd,
12425                          Eina_Bool hidden)
12426 {
12427    E_Border *tmp;
12428    Eina_List *l;
12429
12430    E_OBJECT_CHECK(bd);
12431    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12432
12433    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12434      {
12435        if (hidden)
12436          ecore_x_window_hide(tmp->win);
12437        else
12438          ecore_x_window_show(tmp->win);
12439      }
12440
12441    if (bd->comp_hidden == hidden) return;
12442
12443    bd->comp_hidden = hidden;
12444
12445    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12446      {
12447         ecore_x_composite_window_events_disable(bd->win);
12448         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12449      }
12450    else
12451      {
12452         _e_border_shape_input_rectangle_set(bd);
12453         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12454      }
12455 }
12456
12457 EAPI void
12458 e_border_tmp_input_hidden_push(E_Border *bd)
12459 {
12460    E_Border *tmp;
12461    Eina_List *l;
12462
12463    E_OBJECT_CHECK(bd);
12464    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12465
12466    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12467      e_border_tmp_input_hidden_push(tmp);
12468
12469    bd->tmp_input_hidden++;
12470    if (bd->tmp_input_hidden != 1) return;
12471
12472    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12473      {
12474         ecore_x_composite_window_events_disable(bd->win);
12475         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12476      }
12477    else
12478      {
12479         _e_border_shape_input_rectangle_set(bd);
12480         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12481      }
12482 }
12483
12484 EAPI void
12485 e_border_tmp_input_hidden_pop(E_Border *bd)
12486 {
12487    E_Border *tmp;
12488    Eina_List *l;
12489
12490    E_OBJECT_CHECK(bd);
12491    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12492
12493    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12494      e_border_tmp_input_hidden_pop(tmp);
12495
12496    bd->tmp_input_hidden--;
12497    if (bd->tmp_input_hidden != 0) return;
12498
12499    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12500      {
12501         ecore_x_composite_window_events_disable(bd->win);
12502         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12503      }
12504    else
12505      {
12506         _e_border_shape_input_rectangle_set(bd);
12507         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12508      }
12509 }
12510
12511 EAPI void
12512 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
12513 {
12514    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
12515        ((bd->parent) &&
12516         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
12517          ((bd->parent->focused) &&
12518           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
12519        (just_do_it))
12520      {
12521         if (bd->iconic)
12522           {
12523              if (e_config->clientlist_warp_to_iconified_desktop == 1)
12524                e_desk_show(bd->desk);
12525              
12526              if (!bd->lock_user_iconify)
12527                e_border_uniconify(bd);
12528           }
12529         if ((!bd->iconic) && (!bd->sticky))
12530           e_desk_show(bd->desk);
12531         if (!bd->lock_user_stacking) e_border_raise(bd);
12532         if (!bd->lock_focus_out)
12533           {
12534              /* XXX ooffice does send this request for
12535               config dialogs when the main window gets focus.
12536               causing the pointer to jump back and forth.  */
12537              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
12538                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
12539                ecore_x_pointer_warp(bd->zone->container->win,
12540                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
12541              e_border_focus_set(bd, 1, 1);
12542           }
12543      }
12544 }
12545 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/