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