the repository of RSA merge with private repository.
[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    if (bd->parent) will_ang = bd->parent->client.e.state.rot.curr;
8302    else will_ang = zone->rot.curr;
8303
8304    if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
8305      {
8306         ELBF(ELBT_ROT, 1, bd->client.win,
8307              "%s->parent:0x%08x (support:%d app_set:%d ang:%d)",
8308              (rot.vkbd == bd) ? "vkbd" : "prediction",
8309              bd->parent ? bd->parent->client.win : 0,
8310              bd->parent ? bd->parent->client.e.state.rot.support : -1,
8311              bd->parent ? bd->parent->client.e.state.rot.app_set : -1,
8312              bd->parent ? bd->parent->client.e.state.rot.curr : -1);
8313
8314         if (bd->parent)
8315           {
8316              will_ang = bd->parent->client.e.state.rot.curr;
8317              if ((!bd->parent->client.e.state.rot.support) &&
8318                  (!bd->parent->client.e.state.rot.app_set))
8319                {
8320                   will_ang = 0;
8321                }
8322           }
8323      }
8324
8325    if ((!bd->client.e.state.rot.app_set) &&
8326        (!bd->client.e.state.rot.support))
8327      {
8328         /* hack for magnifier and keyboard popup */
8329         if ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER) ||
8330             (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP))
8331           {
8332              ELB(ELBT_BD, "MAG", bd->client.win);
8333              will_ang = 0;
8334              if ((rot.vkbd) && (rot.vkbd->visible))
8335                will_ang = rot.vkbd->client.e.state.rot.curr;
8336           }
8337      }
8338
8339    if (bd->client.e.state.rot.app_set)
8340      {
8341         /* utility type window should be rotated according to
8342          * rotation of the transient_for window.
8343          */
8344         if ((bd->parent) &&
8345             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
8346           {
8347              will_ang = bd->parent->client.e.state.rot.curr;
8348              if ((!bd->parent->client.e.state.rot.support) &&
8349                  (!bd->parent->client.e.state.rot.app_set))
8350                {
8351                   /* if transient_for window doesn't support rotation feature,
8352                    * then this window should't be rotated.
8353                    * TODO: need to check whether window supports '0' degree or not.
8354                    */
8355                   will_ang = 0;
8356                   ELBF(ELBT_ROT, 0, bd->client.win,
8357                        "GET ROT ang:%d Transient_For:0x%08x Not support rot",
8358                        will_ang, bd->parent->client.win);
8359                }
8360              else
8361                {
8362                   will_ang = _e_border_rotation_get(bd->parent, will_ang);
8363                   ELBF(ELBT_ROT, 0, bd->client.win,
8364                        "GET ROT ang:%d Transient_For:0x%08x",
8365                        will_ang, bd->parent->client.win);
8366                }
8367           }
8368         else
8369           {
8370              will_ang = _e_border_rotation_get(bd, will_ang);
8371              ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d",
8372                   will_ang, bd->parent ? bd->parent->client.win : 0,
8373                   bd->client.netwm.type);
8374           }
8375      }
8376
8377    if (bd->new_client)
8378      {
8379         _ang = _prev_angle_get(bd->client.win);
8380         if (_ang != -1)
8381           bd->client.e.state.rot.curr = _ang;
8382         ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang);
8383      }
8384
8385    if (bd->client.e.state.rot.curr != will_ang)
8386      ret = will_ang;
8387
8388    return ret;
8389 }
8390
8391
8392 static Eina_Bool
8393 _e_border_rotation_zone_set(E_Zone *zone)
8394 {
8395    E_Border_List *l = NULL;
8396    E_Border *bd = NULL;
8397    Eina_Bool ret = EINA_FALSE;
8398
8399    if (!e_config->wm_win_rotation) return EINA_FALSE;
8400
8401    l = e_container_border_list_last(zone->container);
8402    if (!l) return ret;
8403
8404    /* step 1. make the list needs to be rotated. */
8405    while ((bd = e_container_border_list_prev(l)))
8406      {
8407         if (!bd) continue;
8408
8409         // if this window have parent,
8410         // it will be rotated when parent do rotate itself.
8411         // so skip here.
8412         if (bd->parent) continue;
8413
8414         // this type is set by illume.
8415         // if it's not normal type window, will be rotated by illume.
8416         // so skip here.
8417         if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue;
8418
8419         if ((!bd->visible) ||
8420             (!E_INTERSECTS(bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h,
8421                            bd->x, bd->y, bd->w, bd->h))) continue;
8422
8423         if (_e_border_rotatable_check(bd, zone->rot.curr))
8424           {
8425              ELBF(ELBT_ROT, 0, bd->client.win, "ROT_SET(main) curr:%d != TOBE:%d",
8426                   bd->client.e.state.rot.curr, zone->rot.curr);
8427
8428              ret = e_border_rotation_set(bd, zone->rot.curr);
8429           }
8430      }
8431    if (l) e_container_border_list_free(l);
8432
8433    return ret;
8434 }
8435
8436 EAPI Eina_Bool
8437 e_border_rotation_set(E_Border *bd, int rotation)
8438 {
8439    E_Zone *zone = bd->zone;
8440    E_Border_Rotation_Info *info = NULL;
8441    Eina_List *list, *l;
8442    E_Border *child;
8443
8444    if (rotation < 0) return EINA_FALSE;
8445
8446    /* step 1. check if rotation */
8447    if (!_e_border_rotatable_check(bd, rotation)) return EINA_FALSE;
8448
8449    /* step 2. add to async/sync list */
8450    if ((!zone->rot.block_count) &&
8451        ((!bd->visible) ||
8452         (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))))
8453      {
8454         // send rotation change request later.
8455         // and no need to wait message of rotation done.
8456
8457         // async list add
8458         info = E_NEW(E_Border_Rotation_Info, 1);
8459         if (!info) return EINA_FALSE;
8460         ELB(ELBT_ROT, "ADD ASYNC LIST", 0);
8461         info->bd = bd;
8462         info->ang = rotation;
8463         rot.async_list = eina_list_append(rot.async_list, info);
8464
8465         // add job for sending event.
8466         if (!rot.async_job)
8467           {
8468              ELB(ELBT_ROT, "ADD ASYNC_JOB", bd->client.win);
8469              rot.async_job = ecore_job_add(_e_border_cb_rotation_async_job, zone);
8470           }
8471      }
8472    else
8473      {
8474         // sync list add
8475         info = E_NEW(E_Border_Rotation_Info, 1);
8476         if (!info) return EINA_FALSE;
8477         ELB(ELBT_ROT, "ADD SYNC LIST", 0);
8478         info->bd = bd;
8479         info->ang = rotation;
8480         rot.list = eina_list_append(rot.list, info);
8481
8482         // add job for sending event.
8483         if (!rot.sync_job)
8484           {
8485              ELB(ELBT_ROT, "ADD SYNC_JOB", bd->client.win);
8486              rot.sync_job = ecore_job_add(_e_border_cb_rotation_sync_job, zone);
8487           }
8488
8489         // if there is windows over 2 that has to be rotated or is existed window needs resizing,
8490         // lock the screen.
8491         // but, DO NOT lock the screen when rotation block state.
8492         if ((!zone->rot.block_count) &&
8493             ((eina_list_count(rot.list) == 2)))
8494           e_manager_comp_screen_lock(e_manager_current_get());
8495      }
8496
8497    /* step 3. search rotatable window in this window's child */
8498    list = _e_border_sub_borders_new(bd);
8499    EINA_LIST_FOREACH(list, l, child)
8500      {
8501         if (_e_border_rotatable_check(child, rotation))
8502           {
8503              ELBF(ELBT_ROT, 0, child->client.win, "ROT_SET(child) curr:%d != TOBE:%d",
8504                   bd->client.e.state.rot.curr, rotation);
8505              e_border_rotation_set(child, rotation);
8506           }
8507      }
8508
8509    /* step 4. if there is vkbd window, send message to prepare rotation */
8510    if (_e_border_is_vkbd(bd))
8511      {
8512         ELB(ELBT_ROT, "PENDING ROT_REQ UNTIL GET PREP_DONE", rot.vkbd_ctrl_win);
8513         if (rot.prepare_timer)
8514           ecore_timer_del(rot.prepare_timer);
8515         rot.prepare_timer = NULL;
8516
8517         if (rot.done_timer)
8518           ecore_timer_del(rot.done_timer);
8519         rot.done_timer = NULL;
8520
8521         ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win);
8522         ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8523                                                       zone->rot.curr,
8524                                                       EINA_FALSE, 1, 1);
8525         rot.prepare_timer = ecore_timer_add(4.0f,
8526                                             _e_border_rotation_change_prepare_timeout,
8527                                             NULL);
8528
8529         rot.wait_prepare_done = EINA_TRUE;
8530      }
8531
8532    bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8533    bd->client.e.state.rot.curr = rotation;
8534
8535    return EINA_TRUE;
8536 }
8537
8538 // check if border is rotatable in ang.
8539 static Eina_Bool
8540 _e_border_rotatable_check(E_Border *bd, int ang)
8541 {
8542    Eina_Bool ret = EINA_FALSE;
8543
8544    if (!bd) return ret;
8545    if (ang < 0) return ret;
8546    if ((!bd->client.e.state.rot.support) && (!bd->client.e.state.rot.app_set)) return ret;
8547    if (e_object_is_del(E_OBJECT(bd))) return ret;
8548
8549    // same with current angle of window, then false return.
8550    if (ang == bd->client.e.state.rot.curr) return ret;
8551
8552    /* basically WM allows only fullscreen window to rotate */
8553    if (bd->client.e.state.rot.preferred_rot == -1)
8554      {
8555         unsigned int i;
8556
8557         if (bd->client.e.state.rot.app_set)
8558           {
8559              if (bd->client.e.state.rot.available_rots &&
8560                  bd->client.e.state.rot.count)
8561                {
8562                   Eina_Bool found = EINA_FALSE;
8563                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8564                     {
8565                        if (bd->client.e.state.rot.available_rots[i] == ang)
8566                          {
8567                             found = EINA_TRUE;
8568                          }
8569                     }
8570                   if (found) ret = EINA_TRUE;
8571                }
8572           }
8573         else
8574           {
8575              ELB(ELBT_ROT, "DO ROT", 0);
8576              ret = EINA_TRUE;
8577           }
8578      }
8579    // if it has preferred rotation angle,
8580    // it will be rotated at border's evaluation time.
8581    // so skip it.
8582    else if (bd->client.e.state.rot.preferred_rot == ang) ret = EINA_TRUE;
8583
8584    return ret;
8585 }
8586
8587 /* check whether virtual keyboard is visible on the zone */
8588 static Eina_Bool
8589 _e_border_is_vkbd(E_Border *bd)
8590 {
8591    if (!e_config->wm_win_rotation) return EINA_FALSE;
8592
8593    if ((rot.vkbd_ctrl_win) &&
8594        (rot.vkbd == bd) &&
8595        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8596        (rot.vkbd->visible) &&
8597        (rot.vkbd->zone == bd->zone) &&
8598        (E_INTERSECTS(bd->zone->x, bd->zone->y,
8599                      bd->zone->w, bd->zone->h,
8600                      rot.vkbd->x, rot.vkbd->y,
8601                      rot.vkbd->w, rot.vkbd->h)))
8602      {
8603         return EINA_TRUE;
8604      }
8605    return EINA_FALSE;
8606 }
8607
8608 static Eina_Bool
8609 _e_border_rotation_change_floating_pos(E_Border *bd, int *x, int *y)
8610 {
8611    int new_x, new_y;
8612    int min_title_width=96;
8613
8614    if (!bd) return EINA_FALSE;
8615    if (!x || !y) return EINA_FALSE;
8616
8617    new_x = bd->x;
8618    new_y = bd->y;
8619
8620    // Portrait -> Landscape,  x= pre_x*2, y=pre_y/2
8621    // Landscape -> Portrait,  x= pre_x/2, y=pre_y*2
8622    // guaranteeing the minimum size of titlebar shown, min_title_width
8623    // so user can initiate drag&drop action after rotation changed.
8624    if (bd->client.e.state.rot.curr == 0)
8625      {
8626         if (bd->client.e.state.rot.prev == 90)
8627           {
8628              new_x = (bd->zone->h - bd->h - bd->y) / 2;
8629              new_y = 2 * bd->x;
8630           }
8631         else if (bd->client.e.state.rot.prev == 270)
8632           {
8633              new_x = bd->y / 2;
8634              new_y = (bd->zone->w - bd->w - bd->x) * 2;
8635           }
8636         else if (bd->client.e.state.rot.prev == 180)
8637           {
8638              new_x = bd->zone->w - bd->x - bd->w;
8639              new_y = bd->zone->h - bd->y - bd->h;
8640           }
8641
8642         if(new_x + bd->w < min_title_width)
8643           {
8644              new_x = min_title_width - bd->w;
8645           }
8646         else if(new_x > bd->zone->w - min_title_width)
8647           {
8648              new_x = bd->zone->w - min_title_width;
8649           }
8650      }
8651    else if (bd->client.e.state.rot.curr == 90)
8652      {
8653         if (bd->client.e.state.rot.prev == 0)
8654           {
8655              new_x = bd->y / 2;
8656              new_y = bd->zone->h - (2 * bd->x) - bd->w;
8657           }
8658         else if (bd->client.e.state.rot.prev == 270)
8659           {
8660              new_x = bd->zone->w - bd->x - bd->w;
8661              new_y = bd->zone->h - bd->y - bd->h;
8662           }
8663         else if (bd->client.e.state.rot.prev == 180)
8664           {
8665              new_x = (bd->zone->h - bd->y - bd->h) / 2;
8666              new_y = bd->zone->h - (2 * (bd->zone->w - bd->x - bd->w)) - bd->w;
8667           }
8668
8669         if(new_y > bd->zone->h - min_title_width)
8670           {
8671              new_y = bd->zone->h - min_title_width;
8672           }
8673         else if(new_y < min_title_width - bd->w)
8674           {
8675              new_y = min_title_width - bd->w;
8676           }
8677      }
8678    else if (bd->client.e.state.rot.curr == 270)
8679      {
8680         if (bd->client.e.state.rot.prev == 0)
8681           {
8682              new_x = bd->zone->w - bd->h - (bd->y / 2);
8683              new_y = bd->x * 2;
8684           }
8685         else if (bd->client.e.state.rot.prev == 90)
8686           {
8687              new_x = bd->zone->w - bd->x - bd->w;
8688              new_y = bd->zone->h - bd->y - bd->h;
8689           }
8690         else if (bd->client.e.state.rot.prev == 180)
8691           {
8692              new_x = bd->zone->w - bd->x - bd->w;
8693              new_y = bd->zone->h - bd->y - bd->h;
8694
8695              new_x = bd->zone->w - bd->h - ((bd->zone->h - bd->y - bd->h) / 2);
8696              new_y = (bd->zone->w - bd->x - bd->w) * 2;
8697           }
8698
8699         if(new_y >  bd->zone->h - min_title_width)
8700           {
8701              new_y = bd->zone->h - min_title_width;
8702           }
8703         else if( new_y + bd->w < min_title_width)
8704           {
8705              new_y = min_title_width - bd->w ;
8706           }
8707      }
8708    else if (bd->client.e.state.rot.curr == 180)
8709      {
8710         if (bd->client.e.state.rot.prev == 0)
8711           {
8712              new_x = bd->zone->w - bd->x - bd->w;
8713              new_y = bd->zone->h - bd->y - bd->h;
8714           }
8715         else if (bd->client.e.state.rot.prev == 90)
8716           {
8717              new_x = bd->zone->w - ((bd->zone->h - bd->h - bd->y) / 2) - bd->h;
8718              new_y = bd->zone->h - (2 * bd->x) - bd->w;
8719           }
8720         else if (bd->client.e.state.rot.prev == 270)
8721           {
8722              new_x = bd->zone->w - (bd->y / 2) - bd->h;
8723              new_y = bd->zone->h - ((bd->zone->w - bd->w - bd->x) * 2) - bd->w;
8724           }
8725
8726         if(new_x + bd->w < min_title_width)
8727           {
8728              new_x = min_title_width - bd->w;
8729           }
8730         else if(new_x > bd->zone->w - min_title_width)
8731           {
8732              new_x = bd->zone->w - min_title_width;
8733           }
8734      }
8735
8736    ELBF(ELBT_ROT, 0, bd->client.win,
8737         "Floating Mode. ANGLE (%d->%d), POS (%d,%d) -> (%d,%d)",
8738         bd->client.e.state.rot.prev, bd->client.e.state.rot.curr,
8739         bd->x, bd->y, new_x, new_y);
8740
8741    if ((new_x == *x) &&
8742        (new_y == *y))
8743      {
8744         return EINA_FALSE;
8745      }
8746
8747    *x = new_x;
8748    *y = new_y;
8749
8750    return EINA_TRUE;
8751 }
8752
8753 #define SIZE_EQUAL_TO_ZONE(a, z) \
8754    ((((a)->w) == ((z)->w)) &&    \
8755     (((a)->h) == ((z)->h)))
8756 static Eina_Bool
8757 _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h)
8758 {
8759    E_Zone *zone = bd->zone;
8760    int rot_dif;
8761    int _x, _y, _w, _h;
8762    Eina_Bool move = EINA_FALSE;
8763    Eina_Bool hint = EINA_FALSE;
8764    Eina_Bool resize = EINA_FALSE;
8765
8766    if (x) *x = bd->x;
8767    if (y) *y = bd->y;
8768    if (w) *w = bd->w;
8769    if (h) *h = bd->h;
8770
8771    if (SIZE_EQUAL_TO_ZONE(bd, zone)) return resize;
8772
8773    ELB(ELBT_ROT, "SIZE DIFF WITH ZONE", 0);
8774    ELBF(ELBT_ROT, 0, bd->client.win, "ORIGIN_SIZE name:%s (%d,%d) %dx%d",
8775         bd->client.icccm.name, bd->x, bd->y, bd->w, bd->h);
8776
8777    hint = _e_border_rotation_geom_get(bd, bd->zone, rotation,
8778                                       &_x, &_y, &_w, &_h, &move);
8779    if (hint)
8780      {
8781         _e_border_move_resize_internal(bd, _x, _y, _w, _h, EINA_TRUE, move);
8782         resize = EINA_TRUE;
8783         ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
8784              bd->client.icccm.name, _x, _y, _w, _h);
8785      }
8786    else
8787      {
8788         _x = bd->x; _y = bd->y;
8789         _w = bd->w; _h = bd->h;
8790
8791         if (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)
8792           move = _e_border_rotation_change_floating_pos(bd, &_x, &_y);
8793         else
8794           move = EINA_FALSE;
8795
8796         rot_dif = bd->client.e.state.rot.prev - rotation;
8797         if (rot_dif < 0) rot_dif = -rot_dif;
8798         if (rot_dif != 180)
8799           {
8800              if (w != h)
8801                {
8802                   _w = bd->h;
8803                   _h = bd->w;
8804                   resize = EINA_TRUE;
8805
8806                   _e_border_move_resize_internal(bd, _x, _y, _w, _h,
8807                                                  EINA_TRUE, EINA_TRUE);
8808                   ELBF(ELBT_ROT, 0, bd->client.win, "MANUAL_RESIZE name:%s (%d,%d) %dx%d",
8809                        bd->client.icccm.name, _x, _y, _w, _h);
8810
8811                }
8812           }
8813
8814         if (!resize && move)
8815           _e_border_move_internal(bd, _x, _y, EINA_TRUE);
8816      }
8817
8818    if (resize)
8819      {
8820         if (x) *x = _x;
8821         if (y) *y = _y;
8822         if (w) *w = _w;
8823         if (h) *h = _h;
8824      }
8825
8826    return resize;
8827 }
8828
8829 static Eina_Bool
8830 _e_border_cb_window_configure(void *data    __UNUSED__,
8831                               int   ev_type __UNUSED__,
8832                               void         *ev)
8833 {
8834    Ecore_X_Event_Window_Configure *e = ev;
8835    E_Border_Rotation_Info *info = NULL;
8836    Eina_List *l;
8837    Eina_Bool found = EINA_FALSE;
8838
8839    if (!e) return ECORE_CALLBACK_PASS_ON;
8840    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8841
8842    E_Border *bd = e_border_find_by_client_window(e->win);
8843    if (!bd) return ECORE_CALLBACK_PASS_ON;
8844
8845    if (bd->client.e.state.rot.pending_change_request)
8846      {
8847         if ((e->w == bd->w) && (e->h == bd->h))
8848           {
8849              ELB(ELBT_BD, "GET CONFIGURE_NOTI (ROTATION)", bd->client.win);
8850              bd->client.e.state.rot.pending_change_request = 0;
8851
8852              if ((bd->client.e.state.rot.wait_for_done) &&
8853                  (bd->client.e.state.rot.wait_done_ang == bd->client.e.state.rot.curr)) goto end;
8854
8855              // if this window is rotation dependent window and zone is blocked to rotate,
8856              // then skip here, request will be sent after cancel block.
8857              if ((bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_DEPENDENT) &&
8858                  (bd->zone->rot.block_count)) goto end;
8859
8860              EINA_LIST_FOREACH(rot.list, l, info)
8861                 if (info->bd == bd) found = EINA_TRUE;
8862              // send request message if it's async rotation window,
8863              // even if wait prepare done.
8864              if ((found) && (rot.wait_prepare_done)) goto end;
8865
8866              ELBF(ELBT_ROT, 0, bd->client.win,
8867                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
8868                   bd->client.e.state.rot.curr,
8869                   bd->w, bd->h);
8870              ecore_x_e_window_rotation_change_request_send(bd->client.win,
8871                                                            bd->client.e.state.rot.curr);
8872              bd->client.e.state.rot.wait_for_done = 1;
8873              bd->client.e.state.rot.wait_done_ang = bd->client.e.state.rot.curr;
8874           }
8875      }
8876
8877 end:
8878    return ECORE_CALLBACK_PASS_ON;
8879 }
8880
8881 static Eina_Bool
8882 _e_border_rotation_geom_get(E_Border  *bd,
8883                             E_Zone    *zone,
8884                             int        ang,
8885                             int       *x,
8886                             int       *y,
8887                             int       *w,
8888                             int       *h,
8889                             Eina_Bool *move)
8890 {
8891    if (!e_config->wm_win_rotation) return EINA_FALSE;
8892
8893    Eina_Bool res = EINA_FALSE;
8894    Eina_Bool _move = EINA_TRUE;
8895    int _x = bd->x;
8896    int _y = bd->y;
8897    int _w = bd->w;
8898    int _h = bd->h;
8899
8900    if (x) *x = bd->x;
8901    if (y) *y = bd->y;
8902    if (w) *w = bd->w;
8903    if (h) *h = bd->h;
8904    if (move) *move = EINA_TRUE;
8905
8906    if (bd->client.e.state.rot.geom_hint)
8907      {
8908         switch (ang)
8909           {
8910            case   0:
8911               _w = bd->client.e.state.rot.geom[0].w;
8912               _h = bd->client.e.state.rot.geom[0].h;
8913               if (_w == 0) _w = bd->w;
8914               if (_h == 0) _h = bd->h;
8915               _x = 0; _y = zone->h - _h;
8916               break;
8917            case  90:
8918               _w = bd->client.e.state.rot.geom[1].w;
8919               _h = bd->client.e.state.rot.geom[1].h;
8920               if (_w == 0) _w = bd->w;
8921               if (_h == 0) _h = bd->h;
8922               _x = zone->w - _w; _y = 0;
8923               break;
8924            case 180:
8925               _w = bd->client.e.state.rot.geom[2].w;
8926               _h = bd->client.e.state.rot.geom[2].h;
8927               if (_w == 0) _w = bd->w;
8928               if (_h == 0) _h = bd->h;
8929               _x = 0; _y = 0;
8930               break;
8931            case 270:
8932               _w = bd->client.e.state.rot.geom[3].w;
8933               _h = bd->client.e.state.rot.geom[3].h;
8934               if (_w == 0) _w = bd->w;
8935               if (_h == 0) _h = bd->h;
8936               _x = 0; _y = 0;
8937               break;
8938           }
8939
8940         if (x) *x = _x;
8941         if (y) *y = _y;
8942         if (w) *w = _w;
8943         if (h) *h = _h;
8944
8945         if (!((rot.vkbd) && (rot.vkbd == bd)))
8946           {
8947              if (x) *x = bd->x;
8948              if (y) *y = bd->y;
8949              if (move) *move = EINA_FALSE;
8950           }
8951
8952         res = EINA_TRUE;
8953      }
8954
8955    if (res)
8956      {
8957         _x = 0; _y = 0; _w = 0; _h = 0;
8958         if (x) _x = *x;
8959         if (y) _y = *y;
8960         if (w) _w = *w;
8961         if (h) _h = *h;
8962         if (move) _move = *move;
8963
8964         ELBF(ELBT_ROT, 1, bd->client.win,
8965              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
8966              ang, _x, _y, _w, _h, _move);
8967      }
8968
8969    return res;
8970 }
8971 #endif
8972
8973 static Eina_Bool
8974 _e_border_post_move_resize_job(void *data)
8975 {
8976    E_Border *bd;
8977
8978    bd = (E_Border *)data;
8979    if (bd->post_move)
8980      {
8981         E_Border *tmp;
8982         Eina_List *l;
8983
8984         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
8985           ecore_x_window_move(tmp->win,
8986                               bd->x +
8987                               bd->client_inset.l +
8988                               bd->fx.x +
8989                               tmp->client.e.state.video_position.x,
8990                               bd->y +
8991                               bd->client_inset.t +
8992                               bd->fx.y +
8993                               tmp->client.e.state.video_position.y);
8994      }
8995    if (bd->client.e.state.video)
8996      {
8997         E_Border *parent;
8998
8999         parent = bd->client.e.state.video_parent_border;
9000         ecore_x_window_move(bd->win,
9001                             parent->x +
9002                             parent->client_inset.l +
9003                             parent->fx.x +
9004                             bd->client.e.state.video_position.x,
9005                             parent->y +
9006                             parent->client_inset.t +
9007                             parent->fx.y +
9008                             bd->client.e.state.video_position.y);
9009      }
9010    else if ((bd->post_move) && (bd->post_resize))
9011      {
9012         ecore_x_window_move_resize(bd->win,
9013                                    bd->x + bd->fx.x,
9014                                    bd->y + bd->fx.y,
9015                                    bd->w, bd->h);
9016      }
9017    else if (bd->post_move)
9018      {
9019         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
9020      }
9021    else if (bd->post_resize)
9022      {
9023         ecore_x_window_resize(bd->win, bd->w, bd->h);
9024      }
9025
9026    if (bd->client.e.state.video)
9027      {
9028         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
9029                 bd->win,
9030                 bd->client.e.state.video_parent_border->x +
9031                 bd->client.e.state.video_parent_border->client_inset.l +
9032                 bd->client.e.state.video_parent_border->fx.x +
9033                 bd->client.e.state.video_position.x,
9034                 bd->client.e.state.video_parent_border->y +
9035                 bd->client.e.state.video_parent_border->client_inset.t +
9036                 bd->client.e.state.video_parent_border->fx.y +
9037                 bd->client.e.state.video_position.y,
9038                 bd->w, bd->h);
9039      }
9040
9041    if (bd->post_show)
9042      {
9043         if (bd->visible)
9044           {
9045              bd->post_job = NULL;
9046              _e_border_show(bd);
9047           }
9048      }
9049    bd->post_show = 0;
9050    bd->post_move = 0;
9051    bd->post_resize = 0;
9052    bd->post_job = NULL;
9053    return ECORE_CALLBACK_CANCEL;
9054 }
9055
9056 static void
9057 _e_border_container_layout_hook(E_Container *con)
9058 {
9059    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
9060 }
9061
9062 static void
9063 _e_border_eval0(E_Border *bd)
9064 {
9065    int change_urgent = 0;
9066    int rem_change = 0;
9067 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9068    Eina_Bool need_desk_set = EINA_FALSE;
9069 #endif
9070 #ifdef _F_ZONE_WINDOW_ROTATION_
9071    Eina_Bool need_rotation_set = EINA_FALSE;
9072
9073    if ((e_config->wm_win_rotation) &&
9074        (bd->client.icccm.fetch.transient_for))
9075      {
9076         if (((rot.vkbd) && (rot.vkbd == bd)) ||
9077             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
9078           {
9079              need_rotation_set = EINA_TRUE;
9080              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
9081           }
9082      }
9083 #endif
9084
9085    if (e_object_is_del(E_OBJECT(bd)))
9086      {
9087         CRI("_e_border_eval(%p) with deleted border!\n", bd);
9088         bd->changed = 0;
9089         return;
9090      }
9091
9092    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
9093
9094    bd->changes.border = 0;
9095
9096    /* fetch any info queued to be fetched */
9097    if (bd->client.netwm.fetch.state)
9098      {
9099         e_hints_window_state_get(bd);
9100         bd->client.netwm.fetch.state = 0;
9101         rem_change = 1;
9102      }
9103    if (bd->client.icccm.fetch.client_leader)
9104      {
9105         /* TODO: What do to if the client leader isn't mapped yet? */
9106         E_Border *bd_leader = NULL;
9107
9108         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
9109         if (bd->client.icccm.client_leader)
9110           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
9111         if (bd->leader)
9112           {
9113              if (bd->leader != bd_leader)
9114                {
9115                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
9116                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
9117                   bd->leader = NULL;
9118                }
9119              else
9120                bd_leader = NULL;
9121           }
9122         /* If this border is the leader of the group, don't register itself */
9123         if ((bd_leader) && (bd_leader != bd))
9124           {
9125              bd_leader->group = eina_list_append(bd_leader->group, bd);
9126              bd->leader = bd_leader;
9127              /* Only set the window modal to the leader it there is no parent */
9128              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
9129                  ((!bd->parent) || (bd->parent->modal != bd)))
9130                {
9131                   bd->leader->modal = bd;
9132                   if (bd->leader->focused)
9133                     e_border_focus_set(bd, 1, 1);
9134                   else
9135                     {
9136                        Eina_List *l;
9137                        E_Border *child;
9138
9139                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9140                          {
9141                             if ((child != bd) && (child->focused))
9142                               e_border_focus_set(bd, 1, 1);
9143                          }
9144                     }
9145                }
9146           }
9147         bd->client.icccm.fetch.client_leader = 0;
9148         rem_change = 1;
9149      }
9150    if (bd->client.icccm.fetch.title)
9151      {
9152         char *title = ecore_x_icccm_title_get(bd->client.win);
9153         eina_stringshare_replace(&bd->client.icccm.title, title);
9154         if (title) free(title);
9155
9156         if (bd->bg_object)
9157           edje_object_part_text_set(bd->bg_object, "e.text.title",
9158                                     bd->client.icccm.title);
9159         bd->client.icccm.fetch.title = 0;
9160         rem_change = 1;
9161      }
9162    if (bd->client.netwm.fetch.name)
9163      {
9164         char *name;
9165         ecore_x_netwm_name_get(bd->client.win, &name);
9166         eina_stringshare_replace(&bd->client.netwm.name, name);
9167         if (name) free(name);
9168
9169         if (bd->bg_object)
9170           edje_object_part_text_set(bd->bg_object, "e.text.title",
9171                                     bd->client.netwm.name);
9172         bd->client.netwm.fetch.name = 0;
9173         rem_change = 1;
9174      }
9175    if (bd->client.icccm.fetch.name_class)
9176      {
9177         const char *pname, *pclass;
9178         char *nname, *nclass;
9179
9180         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
9181         pname = bd->client.icccm.name;
9182         pclass = bd->client.icccm.class;
9183         bd->client.icccm.name = eina_stringshare_add(nname);
9184         bd->client.icccm.class = eina_stringshare_add(nclass);
9185         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
9186           e_bindings_mapping_change_enable(EINA_FALSE);
9187 #ifdef _F_ZONE_WINDOW_ROTATION_
9188         if (e_config->wm_win_rotation)
9189           {
9190              if ((bd->client.icccm.name) && (bd->client.icccm.class))
9191                {
9192                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
9193                       (!strcmp(bd->client.icccm.class, "ISF")))
9194                     {
9195                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
9196                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
9197                        rot.vkbd = bd;
9198                     }
9199                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
9200                            (!strcmp(bd->client.icccm.class, "ISF")))
9201                     {
9202                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
9203                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
9204                        rot.vkbd_prediction = bd;
9205                     }
9206                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
9207                            (!strcmp(bd->client.icccm.class, "ISF")))
9208                     {
9209                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
9210                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
9211                     }
9212                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
9213                            (!strcmp(bd->client.icccm.class, "ISF")))
9214                     {
9215                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
9216                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
9217                     }
9218                }
9219           }
9220 #endif
9221         if (nname) free(nname);
9222         if (nclass) free(nclass);
9223
9224         if (!((bd->client.icccm.name == pname) &&
9225               (bd->client.icccm.class == pclass)))
9226           bd->changes.icon = 1;
9227
9228         if (pname) eina_stringshare_del(pname);
9229         if (pclass) eina_stringshare_del(pclass);
9230         bd->client.icccm.fetch.name_class = 0;
9231         bd->changes.icon = 1;
9232         rem_change = 1;
9233      }
9234    if (bd->client.icccm.fetch.state)
9235      {
9236         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
9237         bd->client.icccm.fetch.state = 0;
9238         rem_change = 1;
9239      }
9240    if (bd->client.e.fetch.state)
9241      {
9242         e_hints_window_e_state_get(bd);
9243         bd->client.e.fetch.state = 0;
9244         rem_change = 1;
9245      }
9246 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9247    if (bd->client.e.fetch.profile_list)
9248      {
9249         const char **profiles = NULL;
9250         const char *str;
9251         int num = 0, i;
9252
9253         if (bd->client.e.state.profile)
9254           eina_stringshare_del(bd->client.e.state.profile);
9255         EINA_LIST_FREE(bd->client.e.state.profiles, str)
9256           {
9257              if (str) eina_stringshare_del(str);
9258           }
9259         bd->client.e.state.profile = NULL;
9260         bd->client.e.state.profiles = NULL;
9261         bd->client.e.state.profile_list = 0;
9262
9263         if (ecore_x_e_window_profile_list_get(bd->client.win,
9264                                               &profiles, &num))
9265           {
9266              bd->client.e.state.profile_list = 1;
9267              for (i = 0; i < num; i++)
9268                {
9269                   str = eina_stringshare_add(profiles[i]);
9270                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
9271                }
9272
9273              /* We should set desk to contain given border after creating E_BORDER_ADD event.
9274               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
9275               */
9276              need_desk_set = EINA_TRUE;
9277           }
9278         else
9279           {
9280              if (strcmp(bd->desk->window_profile,
9281                         e_config->desktop_default_window_profile) != 0)
9282                {
9283                   ecore_x_e_window_profile_set(bd->client.win,
9284                                                bd->desk->window_profile);
9285                }
9286           }
9287
9288         if (profiles)
9289           {
9290              for (i = 0; i < num; i++)
9291                 if (profiles[i]) free(profiles[i]);
9292              free(profiles);
9293           }
9294
9295         bd->client.e.fetch.profile_list = 0;
9296      }
9297 #endif
9298 #ifdef _F_ZONE_WINDOW_ROTATION_
9299    if ((e_config->wm_win_rotation) &&
9300        (bd->client.e.fetch.rot.support))
9301      {
9302         int ret = 0;
9303         unsigned int support = 0;
9304
9305         ret = ecore_x_window_prop_card32_get
9306           (bd->client.win,
9307           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
9308           &support, 1);
9309
9310         bd->client.e.state.rot.support = 0;
9311         if ((ret == 1) && (support == 1))
9312           bd->client.e.state.rot.support = 1;
9313
9314         if (bd->client.e.state.rot.support)
9315           need_rotation_set = EINA_TRUE;
9316
9317         bd->client.e.fetch.rot.support = 0;
9318      }
9319    if ((e_config->wm_win_rotation) &&
9320        (bd->client.e.fetch.rot.geom_hint))
9321      {
9322         Eina_Rectangle r[4];
9323         int i, x, y, w, h;
9324         bd->client.e.state.rot.geom_hint = 0;
9325         for (i = 0; i < 4; i++)
9326           {
9327              r[i].x = bd->client.e.state.rot.geom[i].x;
9328              r[i].y = bd->client.e.state.rot.geom[i].y;
9329              r[i].w = bd->client.e.state.rot.geom[i].w;
9330              r[i].h = bd->client.e.state.rot.geom[i].h;
9331
9332              bd->client.e.state.rot.geom[i].x = 0;
9333              bd->client.e.state.rot.geom[i].y = 0;
9334              bd->client.e.state.rot.geom[i].w = 0;
9335              bd->client.e.state.rot.geom[i].h = 0;
9336           }
9337
9338         for (i = 0; i < 4; i++)
9339           {
9340              x = 0; y = 0; w = 0; h = 0;
9341              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
9342                {
9343                   bd->client.e.state.rot.geom_hint = 1;
9344                   bd->client.e.state.rot.geom[i].x = x;
9345                   bd->client.e.state.rot.geom[i].y = y;
9346                   bd->client.e.state.rot.geom[i].w = w;
9347                   bd->client.e.state.rot.geom[i].h = h;
9348
9349                   if (!((r[i].x == x) && (r[i].y == y) &&
9350                         (r[i].w == w) && (r[i].h == h)))
9351                     {
9352                        need_rotation_set = EINA_TRUE;
9353                     }
9354                }
9355           }
9356         bd->client.e.fetch.rot.geom_hint = 0;
9357      }
9358    if ((e_config->wm_win_rotation) &&
9359        (bd->client.e.fetch.rot.app_set))
9360      {
9361         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
9362         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
9363         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
9364
9365         if (_prev_app_set != bd->client.e.state.rot.app_set)
9366           need_rotation_set = EINA_TRUE;
9367
9368         bd->client.e.fetch.rot.app_set = 0;
9369      }
9370    if ((e_config->wm_win_rotation) &&
9371        (bd->client.e.fetch.rot.preferred_rot))
9372      {
9373         int r = 0, _prev_preferred_rot;
9374         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
9375         bd->client.e.state.rot.preferred_rot = -1;
9376         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
9377           {
9378              bd->client.e.state.rot.preferred_rot = r;
9379              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
9380           }
9381         else
9382           {
9383              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
9384           }
9385
9386         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
9387           need_rotation_set = EINA_TRUE;
9388
9389         bd->client.e.fetch.rot.preferred_rot = 0;
9390      }
9391    if ((e_config->wm_win_rotation) &&
9392        (bd->client.e.fetch.rot.available_rots))
9393      {
9394         Eina_Bool res, diff = EINA_FALSE;
9395         int *rots = NULL;
9396         unsigned int count = 0, i = 0;
9397         int _prev_rots[4] = { -1, };
9398
9399         if (bd->client.e.state.rot.available_rots)
9400           {
9401              memcpy(_prev_rots,
9402                     bd->client.e.state.rot.available_rots,
9403                     (sizeof(int) * bd->client.e.state.rot.count));
9404
9405              E_FREE(bd->client.e.state.rot.available_rots);
9406           }
9407
9408         bd->client.e.state.rot.count = 0;
9409
9410         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
9411                                                                 &rots, &count);
9412         if ((res) && (count > 0) && (rots))
9413           {
9414              bd->client.e.state.rot.available_rots = rots;
9415              bd->client.e.state.rot.count = count;
9416
9417              for (i = 0; i < count; i++)
9418                {
9419                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
9420                   if ((!diff) && (_prev_rots[i] != rots[i]))
9421                     {
9422                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
9423                             count, i, _prev_rots[i], rots[i]);
9424                        diff = EINA_TRUE;
9425                     }
9426                }
9427           }
9428         else
9429           {
9430              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9431              diff = EINA_TRUE;
9432           }
9433
9434         if (diff) need_rotation_set = EINA_TRUE;
9435         bd->client.e.fetch.rot.available_rots = 0;
9436      }
9437 #endif
9438    if (bd->client.netwm.fetch.type)
9439      {
9440         e_hints_window_type_get(bd);
9441         if ((!bd->lock_border) || (!bd->client.border.name))
9442           bd->client.border.changed = 1;
9443
9444         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9445           {
9446              if (!bd->client.netwm.state.skip_pager)
9447                {
9448                   bd->client.netwm.state.skip_pager = 1;
9449                   bd->client.netwm.update.state = 1;
9450                }
9451              if (!bd->client.netwm.state.skip_taskbar)
9452                {
9453                   bd->client.netwm.state.skip_taskbar = 1;
9454                   bd->client.netwm.update.state = 1;
9455                }
9456           }
9457         bd->client.netwm.fetch.type = 0;
9458      }
9459    if (bd->client.icccm.fetch.machine)
9460      {
9461         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9462
9463         if ((!machine) && (bd->client.icccm.client_leader))
9464           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9465
9466         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9467         if (machine) free(machine);
9468
9469         bd->client.icccm.fetch.machine = 0;
9470         rem_change = 1;
9471      }
9472    if (bd->client.icccm.fetch.command)
9473      {
9474         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9475           {
9476              int i;
9477
9478              for (i = 0; i < bd->client.icccm.command.argc; i++)
9479                free(bd->client.icccm.command.argv[i]);
9480              free(bd->client.icccm.command.argv);
9481           }
9482         bd->client.icccm.command.argc = 0;
9483         bd->client.icccm.command.argv = NULL;
9484         ecore_x_icccm_command_get(bd->client.win,
9485                                   &(bd->client.icccm.command.argc),
9486                                   &(bd->client.icccm.command.argv));
9487         if ((bd->client.icccm.client_leader) &&
9488             (!bd->client.icccm.command.argv))
9489           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9490                                     &(bd->client.icccm.command.argc),
9491                                     &(bd->client.icccm.command.argv));
9492         bd->client.icccm.fetch.command = 0;
9493         rem_change = 1;
9494      }
9495    if (bd->client.icccm.fetch.hints)
9496      {
9497         Eina_Bool accepts_focus, is_urgent;
9498
9499         accepts_focus = EINA_TRUE;
9500         is_urgent = EINA_FALSE;
9501         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9502         if (ecore_x_icccm_hints_get(bd->client.win,
9503                                     &accepts_focus,
9504                                     &bd->client.icccm.initial_state,
9505                                     &bd->client.icccm.icon_pixmap,
9506                                     &bd->client.icccm.icon_mask,
9507                                     &bd->client.icccm.icon_window,
9508                                     &bd->client.icccm.window_group,
9509                                     &is_urgent))
9510           {
9511              bd->client.icccm.accepts_focus = accepts_focus;
9512              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9513                change_urgent = 1;
9514              bd->client.icccm.urgent = is_urgent;
9515
9516              /* If this is a new window, set the state as requested. */
9517              if ((bd->new_client) &&
9518                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9519                {
9520                   e_border_iconify(bd);
9521                   e_border_hide(bd, 1);
9522                }
9523           }
9524         bd->client.icccm.fetch.hints = 0;
9525         rem_change = 1;
9526      }
9527    if (bd->client.icccm.fetch.size_pos_hints)
9528      {
9529         Eina_Bool request_pos;
9530
9531         request_pos = EINA_FALSE;
9532         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9533                                              &request_pos,
9534                                              &bd->client.icccm.gravity,
9535                                              &bd->client.icccm.min_w,
9536                                              &bd->client.icccm.min_h,
9537                                              &bd->client.icccm.max_w,
9538                                              &bd->client.icccm.max_h,
9539                                              &bd->client.icccm.base_w,
9540                                              &bd->client.icccm.base_h,
9541                                              &bd->client.icccm.step_w,
9542                                              &bd->client.icccm.step_h,
9543                                              &bd->client.icccm.min_aspect,
9544                                              &bd->client.icccm.max_aspect))
9545           {
9546              bd->client.icccm.request_pos = request_pos;
9547           }
9548         else
9549           {
9550           }
9551         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9552         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9553         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9554         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9555         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9556         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9557         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9558         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9559         // if doing a resize, fix it up
9560         if (bd->resize_mode != RESIZE_NONE)
9561           {
9562              int x, y, w, h, new_w, new_h;
9563
9564              x = bd->x;
9565              y = bd->y;
9566              w = bd->w;
9567              h = bd->h;
9568              new_w = w;
9569              new_h = h;
9570              e_border_resize_limit(bd, &new_w, &new_h);
9571              if ((bd->resize_mode == RESIZE_TL) ||
9572                  (bd->resize_mode == RESIZE_L) ||
9573                  (bd->resize_mode == RESIZE_BL))
9574                x += (w - new_w);
9575              if ((bd->resize_mode == RESIZE_TL) ||
9576                  (bd->resize_mode == RESIZE_T) ||
9577                  (bd->resize_mode == RESIZE_TR))
9578                y += (h - new_h);
9579              e_border_move_resize(bd, x, y, new_w, new_h);
9580           }
9581         bd->client.icccm.fetch.size_pos_hints = 0;
9582         rem_change = 1;
9583      }
9584    if (bd->client.icccm.fetch.protocol)
9585      {
9586         int i, num;
9587         Ecore_X_WM_Protocol *proto;
9588
9589         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9590         if (proto)
9591           {
9592              for (i = 0; i < num; i++)
9593                {
9594                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9595                     bd->client.icccm.delete_request = 1;
9596                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9597                     bd->client.icccm.take_focus = 1;
9598                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9599                     bd->client.netwm.ping = 1;
9600                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9601                     {
9602                        bd->client.netwm.sync.request = 1;
9603                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9604                                                            &bd->client.netwm.sync.counter))
9605                          bd->client.netwm.sync.request = 0;
9606                     }
9607                }
9608              free(proto);
9609           }
9610         if (bd->client.netwm.ping)
9611           e_border_ping(bd);
9612         else
9613           {
9614              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9615              bd->ping_poller = NULL;
9616           }
9617         bd->client.icccm.fetch.protocol = 0;
9618      }
9619    if (bd->client.icccm.fetch.transient_for)
9620      {
9621         /* TODO: What do to if the transient for isn't mapped yet? */
9622         E_Border *bd_parent = NULL;
9623 #ifdef _F_DEICONIFY_APPROVE_
9624         Eina_Bool change_parent = EINA_FALSE;
9625 #endif
9626
9627         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9628         if (bd->client.icccm.transient_for)
9629           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9630         /* If we already have a parent, remove it */
9631         if (bd->parent)
9632           {
9633              if (bd_parent != bd->parent)
9634                {
9635                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9636                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9637                   bd->parent = NULL;
9638                }
9639              else
9640                bd_parent = NULL;
9641           }
9642         if ((bd_parent) && (bd_parent != bd) &&
9643             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9644           {
9645              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9646              bd->parent = bd_parent;
9647 #ifdef _F_DEICONIFY_APPROVE_
9648              change_parent = EINA_TRUE;
9649 #endif
9650           }
9651         if (bd->parent)
9652           {
9653              e_border_layer_set(bd, bd->parent->layer);
9654              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9655                {
9656                   Ecore_X_Window_Attributes attr;
9657                   bd->parent->modal = bd;
9658                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9659                   bd->parent->saved.event_mask = attr.event_mask.mine;
9660                   bd->parent->lock_close = 1;
9661                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9662                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9663                }
9664
9665              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9666                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9667                bd->take_focus = 1;
9668           }
9669
9670 #ifdef _F_DEICONIFY_APPROVE_
9671         if (change_parent)
9672           {
9673              bd->client.e.state.deiconify_approve.render_done = 0;
9674
9675              E_Border *ancestor_bd;
9676              ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
9677              if ((ancestor_bd) &&
9678                  (!e_object_is_del(E_OBJECT(ancestor_bd))))
9679                {
9680                   ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
9681                   bd->client.e.state.deiconify_approve.ancestor = NULL;
9682
9683                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
9684                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
9685                     {
9686                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
9687                          {
9688                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
9689                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
9690                             e_border_uniconify(ancestor_bd);
9691                          }
9692                     }
9693                }
9694           }
9695 #endif
9696         bd->client.icccm.fetch.transient_for = 0;
9697         rem_change = 1;
9698      }
9699    if (bd->client.icccm.fetch.window_role)
9700      {
9701         char *role = ecore_x_icccm_window_role_get(bd->client.win);
9702         eina_stringshare_replace(&bd->client.icccm.window_role, role);
9703         if (role) free(role);
9704
9705         bd->client.icccm.fetch.window_role = 0;
9706         rem_change = 1;
9707      }
9708    if (bd->client.icccm.fetch.icon_name)
9709      {
9710         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
9711         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
9712         if (icon_name) free(icon_name);
9713
9714         bd->client.icccm.fetch.icon_name = 0;
9715         rem_change = 1;
9716      }
9717    if (bd->client.netwm.fetch.icon_name)
9718      {
9719         char *icon_name;
9720         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
9721         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
9722         if (icon_name) free(icon_name);
9723
9724         bd->client.netwm.fetch.icon_name = 0;
9725         rem_change = 1;
9726      }
9727    if (bd->client.netwm.fetch.icon)
9728      {
9729         int i;
9730         if (bd->client.netwm.icons)
9731           {
9732              for (i = 0; i < bd->client.netwm.num_icons; i++)
9733                {
9734                   free(bd->client.netwm.icons[i].data);
9735                   bd->client.netwm.icons[i].data = NULL;
9736                }
9737              free(bd->client.netwm.icons);
9738           }
9739         bd->client.netwm.icons = NULL;
9740         bd->client.netwm.num_icons = 0;
9741         if (ecore_x_netwm_icons_get(bd->client.win,
9742                                      &bd->client.netwm.icons,
9743                                      &bd->client.netwm.num_icons))
9744           {
9745              // unless the rest of e17 uses border icons OTHER than icon #0
9746              // then free the rest that we don't need anymore.
9747              for (i = 1; i < bd->client.netwm.num_icons; i++)
9748                {
9749                   free(bd->client.netwm.icons[i].data);
9750                   bd->client.netwm.icons[i].data = NULL;
9751                }
9752              bd->client.netwm.num_icons = 1;
9753              bd->changes.icon = 1;
9754           }
9755         bd->client.netwm.fetch.icon = 0;
9756      }
9757    if (bd->client.netwm.fetch.user_time)
9758      {
9759         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
9760         bd->client.netwm.fetch.user_time = 0;
9761      }
9762    if (bd->client.netwm.fetch.strut)
9763      {
9764         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
9765                                              &bd->client.netwm.strut.left,
9766                                              &bd->client.netwm.strut.right,
9767                                              &bd->client.netwm.strut.top,
9768                                              &bd->client.netwm.strut.bottom,
9769                                              &bd->client.netwm.strut.left_start_y,
9770                                              &bd->client.netwm.strut.left_end_y,
9771                                              &bd->client.netwm.strut.right_start_y,
9772                                              &bd->client.netwm.strut.right_end_y,
9773                                              &bd->client.netwm.strut.top_start_x,
9774                                              &bd->client.netwm.strut.top_end_x,
9775                                              &bd->client.netwm.strut.bottom_start_x,
9776                                              &bd->client.netwm.strut.bottom_end_x))
9777           {
9778              ecore_x_netwm_strut_get(bd->client.win,
9779                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
9780                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
9781
9782              bd->client.netwm.strut.left_start_y = 0;
9783              bd->client.netwm.strut.left_end_y = 0;
9784              bd->client.netwm.strut.right_start_y = 0;
9785              bd->client.netwm.strut.right_end_y = 0;
9786              bd->client.netwm.strut.top_start_x = 0;
9787              bd->client.netwm.strut.top_end_x = 0;
9788              bd->client.netwm.strut.bottom_start_x = 0;
9789              bd->client.netwm.strut.bottom_end_x = 0;
9790           }
9791         bd->client.netwm.fetch.strut = 0;
9792      }
9793    if (bd->client.qtopia.fetch.soft_menu)
9794      {
9795         e_hints_window_qtopia_soft_menu_get(bd);
9796         bd->client.qtopia.fetch.soft_menu = 0;
9797         rem_change = 1;
9798      }
9799    if (bd->client.qtopia.fetch.soft_menus)
9800      {
9801         e_hints_window_qtopia_soft_menus_get(bd);
9802         bd->client.qtopia.fetch.soft_menus = 0;
9803         rem_change = 1;
9804      }
9805    if (bd->client.vkbd.fetch.state)
9806      {
9807         e_hints_window_virtual_keyboard_state_get(bd);
9808         bd->client.vkbd.fetch.state = 0;
9809         rem_change = 1;
9810      }
9811    if (bd->client.vkbd.fetch.vkbd)
9812      {
9813         e_hints_window_virtual_keyboard_get(bd);
9814         bd->client.vkbd.fetch.vkbd = 0;
9815         rem_change = 1;
9816      }
9817    if (bd->client.illume.conformant.fetch.conformant)
9818      {
9819         bd->client.illume.conformant.conformant =
9820           ecore_x_e_illume_conformant_get(bd->client.win);
9821         bd->client.illume.conformant.fetch.conformant = 0;
9822      }
9823    if (bd->client.illume.quickpanel.fetch.state)
9824      {
9825         bd->client.illume.quickpanel.state =
9826           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
9827         bd->client.illume.quickpanel.fetch.state = 0;
9828      }
9829    if (bd->client.illume.quickpanel.fetch.quickpanel)
9830      {
9831         bd->client.illume.quickpanel.quickpanel =
9832           ecore_x_e_illume_quickpanel_get(bd->client.win);
9833         bd->client.illume.quickpanel.fetch.quickpanel = 0;
9834      }
9835    if (bd->client.illume.quickpanel.fetch.priority.major)
9836      {
9837         bd->client.illume.quickpanel.priority.major =
9838           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
9839         bd->client.illume.quickpanel.fetch.priority.major = 0;
9840      }
9841    if (bd->client.illume.quickpanel.fetch.priority.minor)
9842      {
9843         bd->client.illume.quickpanel.priority.minor =
9844           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
9845         bd->client.illume.quickpanel.fetch.priority.minor = 0;
9846      }
9847    if (bd->client.illume.quickpanel.fetch.zone)
9848      {
9849         bd->client.illume.quickpanel.zone =
9850           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
9851         bd->client.illume.quickpanel.fetch.zone = 0;
9852      }
9853    if (bd->client.illume.drag.fetch.drag)
9854      {
9855         bd->client.illume.drag.drag =
9856           ecore_x_e_illume_drag_get(bd->client.win);
9857         bd->client.illume.drag.fetch.drag = 0;
9858      }
9859    if (bd->client.illume.drag.fetch.locked)
9860      {
9861         bd->client.illume.drag.locked =
9862           ecore_x_e_illume_drag_locked_get(bd->client.win);
9863         bd->client.illume.drag.fetch.locked = 0;
9864      }
9865    if (bd->client.illume.win_state.fetch.state)
9866      {
9867         bd->client.illume.win_state.state =
9868            ecore_x_e_illume_window_state_get(bd->client.win);
9869         bd->client.illume.win_state.fetch.state = 0;
9870      }
9871    if (bd->changes.shape)
9872      {
9873         Ecore_X_Rectangle *rects;
9874         int num;
9875
9876         bd->changes.shape = 0;
9877         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
9878         if (rects)
9879           {
9880              int cw = 0, ch = 0;
9881
9882              /* This doesn't fix the race, but makes it smaller. we detect
9883               * this and if cw and ch != client w/h then mark this as needing
9884               * a shape change again to fixup next event loop.
9885               */
9886              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9887              if ((cw != bd->client.w) || (ch != bd->client.h))
9888                bd->changes.shape = 1;
9889              if ((num == 1) &&
9890                  (rects[0].x == 0) &&
9891                  (rects[0].y == 0) &&
9892                  ((int)rects[0].width == cw) &&
9893                  ((int)rects[0].height == ch))
9894                {
9895                   if (bd->client.shaped)
9896                     {
9897                        bd->client.shaped = 0;
9898                        if (!bd->bordername)
9899                          bd->client.border.changed = 1;
9900                     }
9901                }
9902              else
9903                {
9904                   if (!bd->client.shaped)
9905                     {
9906                        bd->client.shaped = 1;
9907                        if (!bd->bordername)
9908                          bd->client.border.changed = 1;
9909                     }
9910                }
9911              free(rects);
9912           }
9913         else
9914           {
9915              // FIXME: no rects i think can mean... totally empty window
9916              bd->client.shaped = 0;
9917              if (!bd->bordername)
9918                bd->client.border.changed = 1;
9919           }
9920         bd->need_shape_merge = 1;
9921      }
9922    if (bd->changes.shape_input)
9923      {
9924         Ecore_X_Rectangle *rects;
9925         int num;
9926
9927         bd->changes.shape_input = 0;
9928         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
9929         if (rects)
9930           {
9931              int cw = 0, ch = 0;
9932
9933              /* This doesn't fix the race, but makes it smaller. we detect
9934               * this and if cw and ch != client w/h then mark this as needing
9935               * a shape change again to fixup next event loop.
9936               */
9937              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9938              if ((cw != bd->client.w) || (ch != bd->client.h))
9939                bd->changes.shape_input = 1;
9940              if ((num == 1) &&
9941                  (rects[0].x == 0) &&
9942                  (rects[0].y == 0) &&
9943                  ((int)rects[0].width == cw) &&
9944                  ((int)rects[0].height == ch))
9945                {
9946                   if (bd->shaped_input)
9947                     {
9948                        bd->shaped_input = 0;
9949                        if (!bd->bordername)
9950                          bd->client.border.changed = 1;
9951                     }
9952                }
9953              else
9954                {
9955                   if (!bd->shaped_input)
9956                     {
9957                        bd->shaped_input = 1;
9958                        if (!bd->bordername)
9959                          bd->client.border.changed = 1;
9960                     }
9961                }
9962              free(rects);
9963           }
9964         else
9965           {
9966              bd->shaped_input = 1;
9967              if (!bd->bordername)
9968                bd->client.border.changed = 1;
9969           }
9970         bd->need_shape_merge = 1;
9971      }
9972    if (bd->client.mwm.fetch.hints)
9973      {
9974         int pb;
9975
9976         bd->client.mwm.exists =
9977           ecore_x_mwm_hints_get(bd->client.win,
9978                                 &bd->client.mwm.func,
9979                                 &bd->client.mwm.decor,
9980                                 &bd->client.mwm.input);
9981         pb = bd->client.mwm.borderless;
9982         bd->client.mwm.borderless = 0;
9983         if (bd->client.mwm.exists)
9984           {
9985              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
9986                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
9987                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
9988                bd->client.mwm.borderless = 1;
9989           }
9990         if (bd->client.mwm.borderless != pb)
9991           {
9992              if ((!bd->lock_border) || (!bd->client.border.name))
9993                bd->client.border.changed = 1;
9994           }
9995         bd->client.mwm.fetch.hints = 0;
9996         rem_change = 1;
9997      }
9998    if (bd->client.e.fetch.video_parent)
9999      {
10000         /* unlinking child/parent */
10001         if (bd->client.e.state.video_parent_border != NULL)
10002           {
10003              bd->client.e.state.video_parent_border->client.e.state.video_child =
10004                eina_list_remove
10005                (bd->client.e.state.video_parent_border->client.e.state.video_child,
10006                    bd);
10007           }
10008
10009         ecore_x_window_prop_card32_get(bd->client.win,
10010                                        ECORE_X_ATOM_E_VIDEO_PARENT,
10011                                        &bd->client.e.state.video_parent,
10012                                        1);
10013
10014         /* linking child/parent */
10015         if (bd->client.e.state.video_parent != 0)
10016           {
10017              E_Border *tmp;
10018              Eina_List *l;
10019
10020              EINA_LIST_FOREACH(borders, l, tmp)
10021                if (tmp->client.win == bd->client.e.state.video_parent)
10022                  {
10023                     /* fprintf(stderr, "child added to parent \\o/\n"); */
10024                     bd->client.e.state.video_parent_border = tmp;
10025                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
10026                                                                        bd);
10027                     if (bd->desk != tmp->desk)
10028                       e_border_desk_set(bd, tmp->desk);
10029                     break;
10030                  }
10031           }
10032
10033         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
10034
10035         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
10036         rem_change = 1;
10037      }
10038    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
10039      {
10040         unsigned int xy[2];
10041
10042         ecore_x_window_prop_card32_get(bd->client.win,
10043                                        ECORE_X_ATOM_E_VIDEO_POSITION,
10044                                        xy,
10045                                        2);
10046         bd->client.e.state.video_position.x = xy[0];
10047         bd->client.e.state.video_position.y = xy[1];
10048         bd->client.e.state.video_position.updated = 1;
10049         bd->client.e.fetch.video_position = 0;
10050         bd->x = bd->client.e.state.video_position.x;
10051         bd->y = bd->client.e.state.video_position.y;
10052
10053         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
10054      }
10055    if (bd->client.netwm.update.state)
10056      {
10057         e_hints_window_state_set(bd);
10058         /* Some stats might change the border, like modal */
10059         if (((!bd->lock_border) || (!bd->client.border.name)) &&
10060             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10061           {
10062              bd->client.border.changed = 1;
10063           }
10064         if (bd->parent)
10065           {
10066              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10067                {
10068                   bd->parent->modal = bd;
10069                   if (bd->parent->focused)
10070                     e_border_focus_set(bd, 1, 1);
10071                }
10072           }
10073         else if (bd->leader)
10074           {
10075              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10076                {
10077                   bd->leader->modal = bd;
10078                   if (bd->leader->focused)
10079                     e_border_focus_set(bd, 1, 1);
10080                   else
10081                     {
10082                        Eina_List *l;
10083                        E_Border *child;
10084
10085                        EINA_LIST_FOREACH(bd->leader->group, l, child)
10086                          {
10087                             if ((child != bd) && (child->focused))
10088                               e_border_focus_set(bd, 1, 1);
10089                          }
10090                     }
10091                }
10092           }
10093         bd->client.netwm.update.state = 0;
10094      }
10095
10096    if (bd->new_client)
10097      {
10098         E_Event_Border_Add *ev;
10099         E_Exec_Instance *inst;
10100
10101         ev = E_NEW(E_Event_Border_Add, 1);
10102         ev->border = bd;
10103         e_object_ref(E_OBJECT(bd));
10104         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
10105         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
10106
10107         if ((!bd->lock_border) || (!bd->client.border.name))
10108           bd->client.border.changed = 1;
10109
10110           {
10111              char *str = NULL;
10112
10113              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
10114                  ((bd->client.icccm.client_leader > 0) &&
10115                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
10116                 )
10117                {
10118                   if (!strncmp(str, "E_START|", 8))
10119                     {
10120                        int id;
10121
10122                        id = atoi(str + 8);
10123                        if (id > 0) bd->client.netwm.startup_id = id;
10124                     }
10125                   free(str);
10126                }
10127           }
10128         /* It's ok not to have fetch flag, should only be set on startup
10129          *     * and not changed. */
10130         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
10131           {
10132              if (bd->client.icccm.client_leader)
10133                {
10134                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
10135                     bd->client.netwm.pid = -1;
10136                }
10137              else
10138                bd->client.netwm.pid = -1;
10139           }
10140
10141         if (!bd->re_manage)
10142           {
10143              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
10144                                                         bd->client.netwm.pid);
10145              if ((inst) && (inst->used == 0))
10146                {
10147                   E_Zone *zone;
10148                   E_Desk *desk;
10149
10150                   inst->used++;
10151                   zone = e_container_zone_number_get(bd->zone->container,
10152                                                      inst->screen);
10153                   if (zone) e_border_zone_set(bd, zone);
10154                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
10155                                           inst->desk_y);
10156                   if (desk) e_border_desk_set(bd, desk);
10157                   e_exec_instance_found(inst);
10158                }
10159
10160              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
10161                {
10162                   E_Border *bdl = NULL;
10163
10164                   bdl = bd->parent;
10165                   if (!bdl)
10166                     {
10167                        if (bd->leader) bdl = bd->leader;
10168                     }
10169                   if (!bdl)
10170                     {
10171                        E_Border *child;
10172                        E_Border_List *bl;
10173
10174                        bl = e_container_border_list_first(bd->zone->container);
10175                        while ((child = e_container_border_list_next(bl)))
10176                          {
10177                             if (child == bd) continue;
10178                             if (e_object_is_del(E_OBJECT(child))) continue;
10179                             if ((bd->client.icccm.client_leader) &&
10180                                 (child->client.icccm.client_leader ==
10181                                     bd->client.icccm.client_leader))
10182                               {
10183                                  bdl = child;
10184                                  break;
10185                               }
10186                          }
10187                        e_container_border_list_free(bl);
10188                     }
10189                   if (bdl)
10190                     {
10191                        if (bdl->zone)
10192                          e_border_zone_set(bd, bdl->zone);
10193                        if (bdl->desk)
10194                          e_border_desk_set(bd, bdl->desk);
10195                        else
10196                          e_border_stick(bd);
10197                     }
10198                }
10199           }
10200      }
10201
10202 #ifdef _F_USE_DESK_WINDOW_PROFILE_
10203    if (need_desk_set)
10204      {
10205         E_Container *con = bd->zone->container;
10206         E_Desk *desk = NULL;
10207         Eina_List *l;
10208         const char *str;
10209         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
10210           {
10211              desk = e_container_desk_window_profile_get(con, str);
10212              if (desk)
10213                {
10214                   if (bd->desk != desk)
10215                     {
10216                        bd->client.e.state.profile = eina_stringshare_add(str);
10217                        if (bd->zone != desk->zone)
10218                          e_border_zone_set(bd, desk->zone);
10219                        e_border_desk_set(bd, desk);
10220                     }
10221                   break;
10222                }
10223           }
10224      }
10225 #endif
10226
10227    /* PRE_POST_FETCH calls e_remember apply for new client */
10228    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
10229    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
10230    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
10231
10232 #ifdef _F_ZONE_WINDOW_ROTATION_
10233    if (e_config->wm_win_rotation)
10234      {
10235         if (need_rotation_set)
10236           {
10237              Eina_Bool hint = EINA_FALSE;
10238              int ang = 0;
10239              int x, y, w, h, move;
10240
10241              ELB(ELBT_ROT, "NEED ROT", bd->client.win);
10242              bd->client.e.state.rot.changes = _e_border_rotation_angle_get(bd);
10243
10244              if (bd->client.e.state.rot.changes != -1)
10245                {
10246                   ang = bd->client.e.state.rot.changes;
10247                   bd->changed = 1;
10248                }
10249              else ang = bd->client.e.state.rot.curr;
10250
10251              hint = _e_border_rotation_geom_get(bd, bd->zone, ang, &x, &y, &w, &h, &move);
10252              if (hint)
10253                {
10254                   _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
10255                   ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
10256                        bd->client.icccm.name, x, y, w, h);
10257                }
10258           }
10259      }
10260 #endif
10261
10262    if (bd->need_reparent)
10263      {
10264         if (!bd->internal)
10265           ecore_x_window_save_set_add(bd->client.win);
10266         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
10267         if (bd->visible)
10268           {
10269              if ((bd->new_client) && (bd->internal) &&
10270                  (bd->internal_ecore_evas))
10271                ecore_evas_show(bd->internal_ecore_evas);
10272              ecore_x_window_show(bd->client.win);
10273           }
10274         bd->need_reparent = 0;
10275      }
10276
10277    if ((bd->client.border.changed) && (!bd->shaded) &&
10278        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10279      {
10280         const char *bordername;
10281
10282         if (bd->fullscreen)
10283           bordername = "borderless";
10284         else if (bd->bordername)
10285           bordername = bd->bordername;
10286         else if ((bd->client.mwm.borderless) || (bd->borderless))
10287           bordername = "borderless";
10288         else if (((bd->client.icccm.transient_for != 0) ||
10289                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
10290                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10291                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10292           bordername = "noresize_dialog";
10293         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10294                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10295           bordername = "noresize";
10296         else if (bd->client.shaped)
10297           bordername = "shaped";
10298         else if ((!bd->client.icccm.accepts_focus) &&
10299                  (!bd->client.icccm.take_focus))
10300           bordername = "nofocus";
10301         else if (bd->client.icccm.urgent)
10302           bordername = "urgent";
10303         else if ((bd->client.icccm.transient_for != 0) ||
10304                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10305           bordername = "dialog";
10306         else if (bd->client.netwm.state.modal)
10307           bordername = "modal";
10308         else if ((bd->client.netwm.state.skip_taskbar) ||
10309                  (bd->client.netwm.state.skip_pager))
10310           bordername = "skipped";
10311         else if ((bd->internal) && (bd->client.icccm.class) &&
10312                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
10313           bordername = "internal_fileman";
10314         else
10315           bordername = e_config->theme_default_border_style;
10316         if (!bordername) bordername = "default";
10317
10318         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
10319           {
10320              Evas_Object *o;
10321              char buf[4096];
10322              int ok;
10323
10324              bd->changes.border = 1;
10325              eina_stringshare_replace(&bd->client.border.name, bordername);
10326
10327              if (bd->bg_object)
10328                {
10329                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
10330                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
10331                   bd->changes.size = 1;
10332                   evas_object_del(bd->bg_object);
10333                }
10334              o = edje_object_add(bd->bg_evas);
10335              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
10336              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10337              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
10338                {
10339                   if (bd->client.border.name != e_config->theme_default_border_style)
10340                     {
10341                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
10342                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10343                     }
10344                   if (!ok)
10345                     {
10346                        ok = e_theme_edje_object_set(o, "base/theme/borders",
10347                                                     "e/widgets/border/default/border");
10348                        if (ok)
10349                          {
10350                             /* Reset default border style to default */
10351                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
10352                             e_config_save_queue();
10353                          }
10354                     }
10355                }
10356
10357              bd->shaped = 0;
10358              if (ok)
10359                {
10360                   const char *shape_option, *argb_option;
10361                   int use_argb = 0;
10362
10363                   bd->bg_object = o;
10364
10365                   if ((e_config->use_composite) && (!bd->client.argb))
10366                     {
10367                        argb_option = edje_object_data_get(o, "argb");
10368                        if ((argb_option) && (!strcmp(argb_option, "1")))
10369                          use_argb = 1;
10370
10371                        if (use_argb != bd->argb)
10372                          _e_border_frame_replace(bd, use_argb);
10373
10374                        o = bd->bg_object;
10375                     }
10376
10377                   if (!bd->argb)
10378                     {
10379                        shape_option = edje_object_data_get(o, "shaped");
10380                        if ((shape_option) && (!strcmp(shape_option, "1")))
10381                          bd->shaped = 1;
10382                     }
10383
10384                   if (bd->client.netwm.name)
10385                     edje_object_part_text_set(o, "e.text.title",
10386                                               bd->client.netwm.name);
10387                   else if (bd->client.icccm.title)
10388                     edje_object_part_text_set(o, "e.text.title",
10389                                               bd->client.icccm.title);
10390                }
10391              else
10392                {
10393                   evas_object_del(o);
10394                   bd->bg_object = NULL;
10395                }
10396
10397              _e_border_client_inset_calc(bd);
10398
10399              bd->w += (bd->client_inset.l + bd->client_inset.r);
10400              bd->h += (bd->client_inset.t + bd->client_inset.b);
10401              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
10402              bd->changes.size = 1;
10403              /*  really needed ? */
10404              ecore_x_window_move(bd->client.shell_win,
10405                                  bd->client_inset.l,
10406                                  bd->client_inset.t);
10407
10408              if (bd->maximized != E_MAXIMIZE_NONE)
10409                {
10410                   E_Maximize maximized = bd->maximized;
10411
10412                   /* to force possible resizes */
10413                   bd->maximized = E_MAXIMIZE_NONE;
10414
10415                   _e_border_maximize(bd, maximized);
10416
10417                   /* restore maximized state */
10418                   bd->maximized = maximized;
10419
10420                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
10421                                                bd->maximized & E_MAXIMIZE_VERTICAL);
10422                }
10423              if (bd->bg_object)
10424                {
10425                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
10426                                                   _e_border_cb_signal_bind, bd);
10427                   if (bd->focused)
10428                     {
10429                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
10430                        if (bd->icon_object)
10431                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10432                     }
10433                   if (bd->shaded)
10434                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
10435                   if (bd->sticky)
10436                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
10437                   if (bd->hung)
10438                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
10439                   // FIXME: in eval -do differently
10440                   //         edje_object_message_signal_process(bd->bg_object);
10441                   //         e_border_frame_recalc(bd);
10442
10443                   evas_object_move(bd->bg_object, 0, 0);
10444                   evas_object_resize(bd->bg_object, bd->w, bd->h);
10445                   evas_object_show(bd->bg_object);
10446                }
10447           }
10448         bd->client.border.changed = 0;
10449
10450         if (bd->icon_object)
10451           {
10452              if (bd->bg_object)
10453                {
10454                   evas_object_show(bd->icon_object);
10455                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10456                }
10457              else
10458                evas_object_hide(bd->icon_object);
10459           }
10460      }
10461
10462    if (rem_change) e_remember_update(bd);
10463
10464    if (change_urgent)
10465      {
10466         E_Event_Border_Urgent_Change *ev;
10467
10468         if (bd->client.icccm.urgent)
10469           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
10470         else
10471           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
10472
10473         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
10474         ev->border = bd;
10475         e_object_ref(E_OBJECT(bd));
10476         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
10477                         _e_border_event_border_urgent_change_free, NULL);
10478      }
10479
10480    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10481 }
10482
10483 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10484 static void
10485 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10486 {
10487    E_Border* temp_bd = NULL;
10488    E_Border* top_focusable_bd = NULL;
10489    Eina_Bool is_fully_obscured = EINA_FALSE;
10490    Ecore_X_XRegion *visible_region = NULL;
10491    Ecore_X_XRegion *win_region = NULL;
10492    Ecore_X_Rectangle visible_rect, win_rect;
10493    E_Border_List *bl;
10494
10495    // set the entire visible region as a root geometry
10496    visible_rect.x = bd->zone->x;
10497    visible_rect.y = bd->zone->y;
10498    visible_rect.width = bd->zone->w;
10499    visible_rect.height = bd->zone->h;
10500
10501    visible_region = ecore_x_xregion_new();
10502    if (!visible_region) return;
10503
10504    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10505
10506    bl = e_container_border_list_last(bd->zone->container);
10507    while ((temp_bd = e_container_border_list_prev(bl)))
10508      {
10509         if (temp_bd == bd) break;
10510
10511         if (temp_bd == focused) continue;
10512         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10513         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10514         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10515             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10516             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10517             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10518             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10519             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10520             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10521           {
10522              if (!top_focusable_bd)
10523                {
10524                   top_focusable_bd = temp_bd;
10525                }
10526
10527              win_rect.x = temp_bd->x;
10528              win_rect.y = temp_bd->y;
10529              win_rect.width = temp_bd->w;
10530              win_rect.height = temp_bd->h;
10531
10532              // if it stick out or is bigger than the entire visible region,
10533              // clip it by the entire visible's geometry.
10534              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10535                                   win_rect.width, win_rect.height,
10536                                   visible_rect.x, visible_rect.y,
10537                                   (int)(visible_rect.width), (int)(visible_rect.height));
10538
10539              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10540                {
10541                   win_region = ecore_x_xregion_new();
10542                   if (win_region)
10543                     {
10544                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10545                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10546                        ecore_x_xregion_free(win_region);
10547                        win_region = NULL;
10548
10549                        if (ecore_x_xregion_is_empty(visible_region))
10550                          {
10551                             is_fully_obscured = EINA_TRUE;
10552                             break;
10553                          }
10554                     }
10555                }
10556           }
10557      }
10558
10559    if (is_fully_obscured == EINA_TRUE)
10560      {
10561         e_border_focus_set(top_focusable_bd, 1, 1);
10562      }
10563    else
10564      {
10565         e_border_focus_set(bd, 1, 1);
10566      }
10567
10568    if (visible_region) ecore_x_xregion_free(visible_region);
10569    e_container_border_list_free(bl);
10570 }
10571
10572 static void
10573 _e_border_latest_stacked_focus(E_Border *bd)
10574 {
10575    E_Border *temp_bd;
10576    int root_w, root_h;
10577
10578    root_w = bd->zone->w;
10579    root_h = bd->zone->h;
10580
10581    Eina_List *l;
10582    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10583      {
10584         if (bd == temp_bd) continue;
10585         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10586         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10587
10588         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10589             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10590             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10591             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10592             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10593             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10594             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10595           {
10596              _e_border_latest_stacked_focus_check_set(temp_bd);
10597              break;
10598           }
10599      }
10600 }
10601
10602 static void
10603 _e_border_check_stack (E_Border *bd)
10604 {
10605    E_Border* temp_bd = NULL;
10606    E_Border* top_bd = NULL;
10607    int passed_focus = 0;
10608    int passed = 0;
10609    int root_w = bd->zone->w;
10610    int root_h = bd->zone->h;
10611
10612    E_Border_List *bl;
10613    bl = e_container_border_list_last(bd->zone->container);
10614    while ((temp_bd = e_container_border_list_prev(bl)))
10615      {
10616         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10617         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10618         if ((temp_bd != bd) &&
10619             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10620
10621         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10622            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10623            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10624            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10625            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10626            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10627            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10628           {
10629              if (bd == temp_bd)
10630                {
10631                   if (!passed)
10632                     {
10633                        e_border_focus_set_with_pointer(bd);
10634                        break;
10635                     }
10636                   else
10637                     {
10638                        if (!passed_focus)
10639                          {
10640                             e_border_focus_set_with_pointer(top_bd);
10641                          }
10642                        break;
10643                     }
10644                }
10645              else
10646                {
10647                   if (!passed)
10648                     {
10649                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10650                          {
10651                             if (!bd->lock_focus_out)
10652                               {
10653                                  e_border_focus_latest_set(bd);
10654                               }
10655                          }
10656                     }
10657                }
10658
10659              if (!passed)
10660                {
10661                   passed = 1;
10662                   top_bd = temp_bd;
10663                }
10664
10665              if (temp_bd == focused)
10666                {
10667                   passed_focus = 1;
10668                }
10669           }
10670      }
10671    e_container_border_list_free(bl);
10672 }
10673
10674 static void
10675 _e_border_focus_top_stack_set(E_Border* bd)
10676 {
10677    E_Border *temp_bd;
10678    int root_w, root_h;
10679
10680    root_w = bd->zone->w;
10681    root_h = bd->zone->h;
10682
10683    E_Border_List *bl;
10684    bl = e_container_border_list_last(bd->zone->container);
10685    while ((temp_bd = e_container_border_list_prev(bl)))
10686      {
10687         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10688         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10689         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
10690
10691         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10692            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10693            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10694            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10695            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10696            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10697            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10698           {
10699              if (!temp_bd->focused)
10700                {
10701                   /* this border is the top of the latest stack */
10702                   e_border_focus_set (temp_bd, 1, 1);
10703                }
10704              break;
10705           }
10706      }
10707    e_container_border_list_free(bl);
10708 }
10709 #endif
10710
10711 static void
10712 _e_border_eval(E_Border *bd)
10713 {
10714    E_Event_Border_Property *event;
10715    E_Border_Pending_Move_Resize *pnd;
10716    int rem_change = 0;
10717    int send_event = 1;
10718
10719    if (e_object_is_del(E_OBJECT(bd)))
10720      {
10721         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
10722         bd->changed = 0;
10723         return;
10724      }
10725
10726    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
10727
10728    if (bd->new_client)
10729      {
10730         int zx = 0, zy = 0, zw = 0, zh = 0;
10731
10732         if (bd->zone)
10733           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
10734
10735         /*
10736          * Limit maximum size of windows to useful geometry
10737          */
10738         // TODO: temoporary limited maximize algorithm
10739         // ->
10740         /*if (bd->w > zw)
10741           rw = zw;
10742           else
10743           rw = bd->w;
10744
10745           if (bd->h > zh)
10746           rh = zh;
10747           else
10748           rh = bd->h;
10749
10750           if ((rw != bd->w) || (rh != bd->h))
10751           {
10752           bd->w = rw;
10753           bd->h = rh;
10754           e_border_resize (bd, bd->w, bd->h);
10755           }*/
10756         // <-
10757
10758         if (bd->re_manage)
10759           {
10760              bd->x -= bd->client_inset.l;
10761              bd->y -= bd->client_inset.t;
10762              bd->changes.pos = 1;
10763              bd->placed = 1;
10764           }
10765         else if ((!bd->placed) && (bd->client.icccm.request_pos))
10766           {
10767
10768              Ecore_X_Window_Attributes *att;
10769              int bw;
10770
10771              att = &bd->client.initial_attributes;
10772              bw = att->border * 2;
10773              switch (bd->client.icccm.gravity)
10774                {
10775                 case ECORE_X_GRAVITY_N:
10776                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10777                    bd->y = att->y;
10778                    break;
10779
10780                 case ECORE_X_GRAVITY_NE:
10781                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10782                    bd->y = att->y;
10783                    break;
10784
10785                 case ECORE_X_GRAVITY_E:
10786                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10787                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10788                    break;
10789
10790                 case ECORE_X_GRAVITY_SE:
10791                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10792                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10793                    break;
10794
10795                 case ECORE_X_GRAVITY_S:
10796                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10797                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10798                    break;
10799
10800                 case ECORE_X_GRAVITY_SW:
10801                    bd->x = att->x;
10802                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10803                    break;
10804
10805                 case ECORE_X_GRAVITY_W:
10806                    bd->x = att->x;
10807                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10808                    break;
10809
10810                 case ECORE_X_GRAVITY_CENTER:
10811                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10812                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10813                    break;
10814
10815                 case ECORE_X_GRAVITY_NW:
10816                 default:
10817                    bd->x = att->x;
10818                    bd->y = att->y;
10819                }
10820
10821              /*
10822               * This ensures that windows that like to open with a x/y
10823               * position smaller than returned by e_zone_useful_geometry_get()
10824               * are moved to useful positions.
10825               */
10826              // ->
10827              if (e_config->geometry_auto_move)
10828                {
10829                   if (bd->x < zx)
10830                     bd->x = zx;
10831
10832                   if (bd->y < zy)
10833                     bd->y = zy;
10834
10835                   if (bd->x + bd->w > zx + zw)
10836                     bd->x = zx + zw - bd->w;
10837
10838                   if (bd->y + bd->h > zy + zh)
10839                     bd->y = zy + zh - bd->h;
10840                   // <--
10841
10842                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
10843                     {
10844                        bd->changes.pos = 1;
10845                        bd->placed = 1;
10846                     }
10847                }
10848              else
10849                {
10850                   bd->changes.pos = 1;
10851                   bd->placed = 1;
10852                }
10853           }
10854         if (!bd->placed)
10855           {
10856              /* FIXME: special placement for dialogs etc. etc. etc goes
10857               * here */
10858              /* FIXME: what if parent is not on this desktop - or zone? */
10859              if ((bd->parent) && (bd->parent->visible))
10860                {
10861                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
10862                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
10863                   bd->changes.pos = 1;
10864                   bd->placed = 1;
10865                }
10866 #if 0
10867              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10868                {
10869                   /* TODO: Place in center of group */
10870                }
10871 #endif
10872              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
10873                {
10874                   bd->x = zx + ((zw - bd->w) / 2);
10875                   bd->y = zy + ((zh - bd->h) / 2);
10876                   bd->changes.pos = 1;
10877                   bd->placed = 1;
10878                }
10879           }
10880         if (!bd->placed)
10881           {
10882              Eina_List *skiplist = NULL;
10883              int new_x, new_y;
10884
10885              if (zw > bd->w)
10886                new_x = zx + (rand() % (zw - bd->w));
10887              else
10888                new_x = zx;
10889              if (zh > bd->h)
10890                new_y = zy + (rand() % (zh - bd->h));
10891              else
10892                new_y = zy;
10893
10894              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
10895                {
10896                   skiplist = eina_list_append(skiplist, bd);
10897                   if (bd->desk)
10898                     e_place_desk_region_smart(bd->desk, skiplist,
10899                                               bd->x, bd->y, bd->w, bd->h,
10900                                               &new_x, &new_y);
10901                   else
10902                     e_place_zone_region_smart(bd->zone, skiplist,
10903                                               bd->x, bd->y, bd->w, bd->h,
10904                                               &new_x, &new_y);
10905                   eina_list_free(skiplist);
10906                }
10907              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
10908                {
10909                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
10910                                       &new_x, &new_y);
10911                }
10912              else
10913                {
10914                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
10915                                       bd->client_inset.t, &new_x, &new_y);
10916                }
10917              bd->x = new_x;
10918              bd->y = new_y;
10919              bd->changes.pos = 1;
10920           }
10921
10922         EINA_LIST_FREE(bd->pending_move_resize, pnd)
10923           {
10924              if ((!bd->lock_client_location) && (pnd->move))
10925                {
10926                   bd->x = pnd->x;
10927                   bd->y = pnd->y;
10928                   bd->changes.pos = 1;
10929                   bd->placed = 1;
10930                   if (pnd->without_border)
10931                     {
10932                        bd->x -= bd->client_inset.l;
10933                        bd->y -= bd->client_inset.t;
10934                     }
10935                }
10936              if ((!bd->lock_client_size) && (pnd->resize))
10937                {
10938                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
10939                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
10940                   bd->client.w = pnd->w;
10941                   bd->client.h = pnd->h;
10942                   bd->changes.size = 1;
10943                }
10944
10945              free(pnd);
10946           }
10947
10948         /* Recreate state */
10949         e_hints_window_init(bd);
10950         if ((bd->client.e.state.centered) &&
10951             ((!bd->remember) ||
10952              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
10953           {
10954              bd->x = zx + (zw - bd->w) / 2;
10955              bd->y = zy + (zh - bd->h) / 2;
10956              bd->changes.pos = 1;
10957              bd->placed = 1;
10958           }
10959
10960         _e_border_client_move_resize_send(bd);
10961
10962         /* if the explicit geometry request asks for the app to be
10963          * in another zone - well move it there */
10964         {
10965            E_Zone *zone;
10966
10967            zone = e_container_zone_at_point_get(bd->zone->container,
10968                                                 bd->x + (bd->w / 2),
10969                                                 bd->y + (bd->h / 2));
10970            if (!zone)
10971              zone = e_container_zone_at_point_get(bd->zone->container,
10972                                                   bd->x,
10973                                                   bd->y);
10974            if (!zone)
10975              zone = e_container_zone_at_point_get(bd->zone->container,
10976                                                   bd->x + bd->w - 1,
10977                                                   bd->y);
10978            if (!zone)
10979              zone = e_container_zone_at_point_get(bd->zone->container,
10980                                                   bd->x + bd->w - 1,
10981                                                   bd->y + bd->h - 1);
10982            if (!zone)
10983              zone = e_container_zone_at_point_get(bd->zone->container,
10984                                                   bd->x,
10985                                                   bd->y + bd->h - 1);
10986            if ((zone) && (zone != bd->zone))
10987              e_border_zone_set(bd, zone);
10988         }
10989      }
10990
10991    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
10992
10993    /* effect changes to the window border itself */
10994    if ((bd->changes.shading))
10995      {
10996         /*  show at start of unshade (but don't hide until end of shade) */
10997         if (bd->shaded)
10998           ecore_x_window_raise(bd->client.shell_win);
10999         bd->changes.shading = 0;
11000         rem_change = 1;
11001      }
11002    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
11003      {
11004         if (bd->shaded)
11005           ecore_x_window_lower(bd->client.shell_win);
11006         else
11007           ecore_x_window_raise(bd->client.shell_win);
11008         bd->changes.shaded = 0;
11009         rem_change = 1;
11010      }
11011    else if ((bd->changes.shaded) && (bd->changes.pos))
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.size = 1;
11018         bd->changes.shaded = 0;
11019         rem_change = 1;
11020      }
11021    else if ((bd->changes.shaded) && (bd->changes.size))
11022      {
11023         if (bd->shaded)
11024           ecore_x_window_lower(bd->client.shell_win);
11025         else
11026           ecore_x_window_raise(bd->client.shell_win);
11027         bd->changes.shaded = 0;
11028         rem_change = 1;
11029      }
11030    else if (bd->changes.shaded)
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.size = 1;
11037         bd->changes.shaded = 0;
11038         rem_change = 1;
11039      }
11040
11041    if (bd->changes.size)
11042      {
11043         int x = 0, y = 0, xx = 0, yy = 0;
11044
11045         if ((bd->shaded) && (!bd->shading))
11046           {
11047              evas_obscured_clear(bd->bg_evas);
11048           }
11049         else
11050           {
11051              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
11052              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
11053
11054              evas_obscured_clear(bd->bg_evas);
11055              evas_obscured_rectangle_add(bd->bg_evas,
11056                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
11057
11058              if (bd->shading)
11059                {
11060                   if (bd->shade.dir == E_DIRECTION_UP)
11061                     {
11062                        y = yy - bd->client.h;
11063                     }
11064                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11065                     {
11066                        x = xx - bd->client.w;
11067                     }
11068                }
11069           }
11070
11071         if (bd->client.e.state.video)
11072           {
11073              if (bd->client.e.state.video_position.updated)
11074                {
11075                   ecore_x_window_move(bd->win,
11076                                       bd->client.e.state.video_parent_border->x +
11077                                       bd->client.e.state.video_parent_border->client_inset.l +
11078                                       bd->client.e.state.video_parent_border->fx.x +
11079                                       bd->client.e.state.video_position.x,
11080                                       bd->client.e.state.video_parent_border->y +
11081                                       bd->client.e.state.video_parent_border->client_inset.t +
11082                                       bd->client.e.state.video_parent_border->fx.y +
11083                                       bd->client.e.state.video_position.y);
11084                   bd->client.e.state.video_position.updated = 0;
11085                }
11086           }
11087         else if (!bd->changes.pos)
11088           {
11089              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11090              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11091              bd->post_resize = 1;
11092           }
11093         else
11094           {
11095              E_Border *tmp;
11096              Eina_List *l;
11097
11098              ecore_x_window_move_resize(bd->win,
11099                                         bd->x + bd->fx.x,
11100                                         bd->y + bd->fx.y,
11101                                         bd->w, bd->h);
11102
11103              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
11104                ecore_x_window_move(tmp->win,
11105                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
11106                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
11107           }
11108
11109         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
11110
11111         if ((!bd->shaded) || (bd->shading))
11112           ecore_x_window_move_resize(bd->client.shell_win,
11113                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
11114
11115         if (bd->internal_ecore_evas)
11116           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
11117         else if (!bd->client.e.state.video)
11118           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
11119
11120         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
11121         evas_object_resize(bd->bg_object, bd->w, bd->h);
11122         e_container_shape_resize(bd->shape, bd->w, bd->h);
11123         if (bd->changes.pos)
11124           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11125
11126         _e_border_client_move_resize_send(bd);
11127
11128         bd->changes.pos = 0;
11129         bd->changes.size = 0;
11130         rem_change = 1;
11131      }
11132    else if (bd->changes.pos)
11133      {
11134         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11135         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11136         bd->post_move = 1;
11137
11138         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11139
11140         _e_border_client_move_resize_send(bd);
11141
11142         bd->changes.pos = 0;
11143         rem_change = 1;
11144      }
11145
11146    if (bd->changes.reset_gravity)
11147      {
11148         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
11149         bd->changes.reset_gravity = 0;
11150         rem_change = 1;
11151      }
11152
11153    if (bd->need_shape_merge)
11154      {
11155         _e_border_shape_input_rectangle_set(bd);
11156         if ((bd->shaped) || (bd->client.shaped))
11157           {
11158              Ecore_X_Window twin, twin2;
11159              int x, y;
11160
11161              twin = ecore_x_window_override_new
11162                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
11163              if (bd->shaped)
11164                ecore_x_window_shape_window_set(twin, bd->bg_win);
11165              else
11166                {
11167                   Ecore_X_Rectangle rects[4];
11168
11169                   rects[0].x = 0;
11170                   rects[0].y = 0;
11171                   rects[0].width = bd->w;
11172                   rects[0].height = bd->client_inset.t;
11173                   rects[1].x = 0;
11174                   rects[1].y = bd->client_inset.t;
11175                   rects[1].width = bd->client_inset.l;
11176                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11177                   rects[2].x = bd->w - bd->client_inset.r;
11178                   rects[2].y = bd->client_inset.t;
11179                   rects[2].width = bd->client_inset.r;
11180                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11181                   rects[3].x = 0;
11182                   rects[3].y = bd->h - bd->client_inset.b;
11183                   rects[3].width = bd->w;
11184                   rects[3].height = bd->client_inset.b;
11185                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
11186                }
11187              twin2 = ecore_x_window_override_new
11188                (bd->zone->container->scratch_win, 0, 0,
11189                 bd->w - bd->client_inset.l - bd->client_inset.r,
11190                 bd->h - bd->client_inset.t - bd->client_inset.b);
11191              x = 0;
11192              y = 0;
11193              if ((bd->shading) || (bd->shaded))
11194                {
11195                   if (bd->shade.dir == E_DIRECTION_UP)
11196                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
11197                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11198                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
11199                }
11200              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
11201                                                 x, y);
11202              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
11203                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
11204                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
11205              ecore_x_window_shape_window_add_xy(twin, twin2,
11206                                                 bd->client_inset.l,
11207                                                 bd->client_inset.t);
11208              ecore_x_window_free(twin2);
11209              ecore_x_window_shape_window_set(bd->win, twin);
11210              ecore_x_window_free(twin);
11211           }
11212         else
11213           ecore_x_window_shape_mask_set(bd->win, 0);
11214         //      bd->need_shape_export = 1;
11215         bd->need_shape_merge = 0;
11216      }
11217
11218    if (bd->need_shape_export)
11219      {
11220         Ecore_X_Rectangle *rects, *orects;
11221         int num;
11222
11223         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
11224         if (rects)
11225           {
11226              int changed;
11227
11228              changed = 1;
11229              if ((num == bd->shape_rects_num) && (bd->shape_rects))
11230                {
11231                   int i;
11232
11233                   orects = bd->shape_rects;
11234                   changed = 0;
11235                   for (i = 0; i < num; i++)
11236                     {
11237                        if (rects[i].x < 0)
11238                          {
11239                             rects[i].width -= rects[i].x;
11240                             rects[i].x = 0;
11241                          }
11242                        if ((rects[i].x + (int)rects[i].width) > bd->w)
11243                          rects[i].width = rects[i].width - rects[i].x;
11244                        if (rects[i].y < 0)
11245                          {
11246                             rects[i].height -= rects[i].y;
11247                             rects[i].y = 0;
11248                          }
11249                        if ((rects[i].y + (int)rects[i].height) > bd->h)
11250                          rects[i].height = rects[i].height - rects[i].y;
11251
11252                        if ((orects[i].x != rects[i].x) ||
11253                            (orects[i].y != rects[i].y) ||
11254                            (orects[i].width != rects[i].width) ||
11255                            (orects[i].height != rects[i].height))
11256                          {
11257                             changed = 1;
11258                             break;
11259                          }
11260                     }
11261                }
11262              if (changed)
11263                {
11264                   if (bd->client.shaped)
11265                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
11266                   else
11267                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
11268                   E_FREE(bd->shape_rects);
11269                   bd->shape_rects = rects;
11270                   bd->shape_rects_num = num;
11271                   e_container_shape_rects_set(bd->shape, rects, num);
11272                }
11273              else
11274                free(rects);
11275           }
11276         else
11277           {
11278              E_FREE(bd->shape_rects);
11279              bd->shape_rects = NULL;
11280              bd->shape_rects_num = 0;
11281              e_container_shape_rects_set(bd->shape, NULL, 0);
11282           }
11283         bd->need_shape_export = 0;
11284      }
11285
11286    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
11287      {
11288         int x, y;
11289
11290         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
11291         if ((!bd->placed) && (!bd->re_manage) &&
11292             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
11293             (!((bd->client.icccm.transient_for != 0) ||
11294                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
11295             (!bdmove) && (!bdresize))
11296           {
11297              /* Set this window into moving state */
11298
11299              bd->cur_mouse_action = e_action_find("window_move");
11300              if (bd->cur_mouse_action)
11301                {
11302                   if ((!bd->cur_mouse_action->func.end_mouse) &&
11303                       (!bd->cur_mouse_action->func.end))
11304                     bd->cur_mouse_action = NULL;
11305                   if (bd->cur_mouse_action)
11306                     {
11307                        bd->x = x - (bd->w >> 1);
11308                        bd->y = y - (bd->client_inset.t >> 1);
11309                        bd->changed = 1;
11310                        bd->changes.pos = 1;
11311
11312                        _e_border_client_move_resize_send(bd);
11313                     }
11314                }
11315           }
11316
11317         _e_border_show(bd);
11318
11319         if (bd->cur_mouse_action)
11320           {
11321              bd->moveinfo.down.x = bd->x + bd->fx.x;
11322              bd->moveinfo.down.y = bd->y + bd->fx.y;
11323              bd->moveinfo.down.w = bd->w;
11324              bd->moveinfo.down.h = bd->h;
11325              bd->mouse.current.mx = x;
11326              bd->mouse.current.my = y;
11327              bd->moveinfo.down.button = 0;
11328              bd->moveinfo.down.mx = x;
11329              bd->moveinfo.down.my = y;
11330
11331              grabbed = 1;
11332              e_object_ref(E_OBJECT(bd->cur_mouse_action));
11333              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
11334              if (e_config->border_raise_on_mouse_action)
11335                e_border_raise(bd);
11336              e_border_focus_set(bd, 1, 1);
11337           }
11338         bd->changes.visible = 0;
11339         rem_change = 1;
11340      }
11341
11342    if (bd->changes.icon)
11343      {
11344         if (bd->desktop)
11345           {
11346              efreet_desktop_free(bd->desktop);
11347              bd->desktop = NULL;
11348           }
11349         if (bd->icon_object)
11350           {
11351              evas_object_del(bd->icon_object);
11352              bd->icon_object = NULL;
11353           }
11354         if (bd->remember && bd->remember->prop.desktop_file)
11355           {
11356              const char *desktop = bd->remember->prop.desktop_file;
11357
11358              bd->desktop = efreet_desktop_get(desktop);
11359              if (!bd->desktop)
11360                bd->desktop = efreet_util_desktop_name_find(desktop);
11361           }
11362         if (!bd->desktop)
11363           {
11364              if ((bd->client.icccm.name) && (bd->client.icccm.class))
11365                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
11366                                                                bd->client.icccm.class);
11367           }
11368         if (!bd->desktop)
11369           {
11370              /* libreoffice and maybe others match window class
11371                 with .desktop file name */
11372              if (bd->client.icccm.class)
11373                {
11374                   char buf[128];
11375                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
11376                   bd->desktop = efreet_util_desktop_file_id_find(buf);
11377                }
11378           }
11379         if (!bd->desktop)
11380           {
11381              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
11382                                                       bd->client.netwm.pid);
11383              if (bd->desktop) efreet_desktop_ref(bd->desktop);
11384           }
11385         if (!bd->desktop && bd->client.icccm.name)
11386           {
11387              /* this works for most cases as fallback. useful when app is
11388                 run from a shell  */
11389              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
11390           }
11391         if (!bd->desktop && bd->client.icccm.transient_for)
11392           {
11393              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
11394              if (bd2 && bd2->desktop)
11395                {
11396                   efreet_desktop_ref(bd2->desktop);
11397                   bd->desktop = bd2->desktop;
11398                }
11399           }
11400         if (bd->desktop)
11401           {
11402              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
11403                                             bd->desktop->orig_path);
11404           }
11405
11406         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
11407         if ((bd->focused) && (bd->icon_object))
11408           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
11409         if (bd->bg_object)
11410           {
11411              evas_object_show(bd->icon_object);
11412              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
11413           }
11414         else
11415           evas_object_hide(bd->icon_object);
11416
11417         {
11418            E_Event_Border_Icon_Change *ev;
11419
11420            ev = E_NEW(E_Event_Border_Icon_Change, 1);
11421            ev->border = bd;
11422            e_object_ref(E_OBJECT(bd));
11423            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
11424            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
11425                            _e_border_event_border_icon_change_free, NULL);
11426         }
11427         bd->changes.icon = 0;
11428      }
11429
11430    bd->new_client = 0;
11431    bd->changed = 0;
11432    bd->changes.stack = 0;
11433    bd->changes.prop = 0;
11434
11435    if (bd->client.e.state.rot.changes != -1)
11436      {
11437         e_border_rotation_set(bd, bd->client.e.state.rot.changes);
11438         bd->client.e.state.rot.changes = -1;
11439      }
11440
11441    if ((bd->take_focus) || (bd->want_focus))
11442      {
11443         bd->take_focus = 0;
11444 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11445         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
11446             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
11447             (bd->want_focus))
11448 #else // original
11449         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
11450 #endif
11451           {
11452              bd->want_focus = 0;
11453 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11454              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
11455                 _e_border_check_stack(bd);
11456              else
11457 #endif
11458              e_border_focus_set_with_pointer(bd);
11459           }
11460         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11461           {
11462              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
11463                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
11464                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
11465                    e_border_focused_get())))
11466                {
11467                   e_border_focus_set_with_pointer(bd);
11468                }
11469           }
11470         else
11471           {
11472              /* focus window by default when it is the only one on desk */
11473              E_Border *bd2 = NULL;
11474              Eina_List *l;
11475              EINA_LIST_FOREACH(focus_stack, l, bd2)
11476                {
11477                   if (bd == bd2) continue;
11478                   if ((!bd2->iconic) && (bd2->visible) &&
11479                       ((bd->desk == bd2->desk) || bd2->sticky))
11480                     break;
11481                }
11482
11483              if (!bd2)
11484                {
11485                   e_border_focus_set_with_pointer(bd);
11486                }
11487           }
11488      }
11489
11490    if (bd->need_maximize)
11491      {
11492         E_Maximize max;
11493         max = bd->maximized;
11494         bd->maximized = E_MAXIMIZE_NONE;
11495         e_border_maximize(bd, max);
11496         bd->need_maximize = 0;
11497      }
11498
11499    if (bd->need_fullscreen)
11500      {
11501         e_border_fullscreen(bd, e_config->fullscreen_policy);
11502         bd->need_fullscreen = 0;
11503      }
11504
11505    if (rem_change)
11506      e_remember_update(bd);
11507
11508    if (send_event) // FIXME: send only if a property changed - above need to
11509      { // check on that. for now - always send.
11510         event = E_NEW(E_Event_Border_Property, 1);
11511         event->border = bd;
11512         e_object_ref(E_OBJECT(bd));
11513         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11514      }
11515    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11516 }
11517
11518 static void
11519 _e_border_moveinfo_gather(E_Border   *bd,
11520                           const char *source)
11521 {
11522    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11523    else if (e_util_glob_match(source, "mouse,*,2"))
11524      bd->moveinfo.down.button = 2;
11525    else if (e_util_glob_match(source, "mouse,*,3"))
11526      bd->moveinfo.down.button = 3;
11527    else bd->moveinfo.down.button = 0;
11528    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11529      {
11530         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11531         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11532      }
11533    else
11534      {
11535         bd->moveinfo.down.mx = bd->mouse.current.mx;
11536         bd->moveinfo.down.my = bd->mouse.current.my;
11537      }
11538 }
11539
11540 static void
11541 _e_border_resize_handle(E_Border *bd)
11542 {
11543    int x, y, w, h;
11544    int new_x, new_y, new_w, new_h;
11545    int tw, th;
11546    Eina_List *skiplist = NULL;
11547
11548    x = bd->x;
11549    y = bd->y;
11550    w = bd->w;
11551    h = bd->h;
11552
11553    if ((bd->resize_mode == RESIZE_TR) ||
11554        (bd->resize_mode == RESIZE_R) ||
11555        (bd->resize_mode == RESIZE_BR))
11556      {
11557         if ((bd->moveinfo.down.button >= 1) &&
11558             (bd->moveinfo.down.button <= 3))
11559           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11560             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11561         else
11562           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11563      }
11564    else if ((bd->resize_mode == RESIZE_TL) ||
11565             (bd->resize_mode == RESIZE_L) ||
11566             (bd->resize_mode == RESIZE_BL))
11567      {
11568         if ((bd->moveinfo.down.button >= 1) &&
11569             (bd->moveinfo.down.button <= 3))
11570           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11571             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11572         else
11573           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11574      }
11575
11576    if ((bd->resize_mode == RESIZE_TL) ||
11577        (bd->resize_mode == RESIZE_T) ||
11578        (bd->resize_mode == RESIZE_TR))
11579      {
11580         if ((bd->moveinfo.down.button >= 1) &&
11581             (bd->moveinfo.down.button <= 3))
11582           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11583             (bd->mouse.current.my - bd->moveinfo.down.my);
11584         else
11585           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11586      }
11587    else if ((bd->resize_mode == RESIZE_BL) ||
11588             (bd->resize_mode == RESIZE_B) ||
11589             (bd->resize_mode == RESIZE_BR))
11590      {
11591         if ((bd->moveinfo.down.button >= 1) &&
11592             (bd->moveinfo.down.button <= 3))
11593           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11594             (bd->mouse.current.my - bd->moveinfo.down.my);
11595         else
11596           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11597      }
11598
11599    tw = bd->w;
11600    th = bd->h;
11601
11602    if ((bd->resize_mode == RESIZE_TL) ||
11603        (bd->resize_mode == RESIZE_L) ||
11604        (bd->resize_mode == RESIZE_BL))
11605      x += (tw - w);
11606    if ((bd->resize_mode == RESIZE_TL) ||
11607        (bd->resize_mode == RESIZE_T) ||
11608        (bd->resize_mode == RESIZE_TR))
11609      y += (th - h);
11610
11611    skiplist = eina_list_append(skiplist, bd);
11612    e_resist_container_border_position(bd->zone->container, skiplist,
11613                                       bd->x, bd->y, bd->w, bd->h,
11614                                       x, y, w, h,
11615                                       &new_x, &new_y, &new_w, &new_h);
11616    eina_list_free(skiplist);
11617
11618    w = new_w;
11619    h = new_h;
11620    e_border_resize_limit(bd, &new_w, &new_h);
11621    if ((bd->resize_mode == RESIZE_TL) ||
11622        (bd->resize_mode == RESIZE_L) ||
11623        (bd->resize_mode == RESIZE_BL))
11624      new_x += (w - new_w);
11625    if ((bd->resize_mode == RESIZE_TL) ||
11626        (bd->resize_mode == RESIZE_T) ||
11627        (bd->resize_mode == RESIZE_TR))
11628      new_y += (h - new_h);
11629
11630    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11631 }
11632
11633 static Eina_Bool
11634 _e_border_shade_animator(void *data)
11635 {
11636    E_Border *bd = data;
11637    double dt, val;
11638    double dur = bd->client.h / e_config->border_shade_speed;
11639
11640    dt = ecore_loop_time_get() - bd->shade.start;
11641    val = dt / dur;
11642
11643    if (val < 0.0) val = 0.0;
11644    else if (val > 1.0) val = 1.0;
11645
11646    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11647      {
11648         bd->shade.val =
11649            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
11650         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11651      }
11652    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
11653      {
11654         bd->shade.val =
11655            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
11656         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11657      }
11658    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
11659      {
11660         bd->shade.val =
11661            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
11662         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11663      }
11664    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
11665      {
11666         bd->shade.val =
11667            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11668         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11669      }
11670    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
11671      {
11672         bd->shade.val =
11673            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
11674         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11675      }
11676    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
11677      {
11678         bd->shade.val =
11679            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
11680         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11681      }
11682    else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
11683      {
11684         bd->shade.val =
11685            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.0);
11686         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11687      }
11688    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE)
11689      {
11690         bd->shade.val =
11691            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
11692         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11693      }
11694    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
11695      {
11696         bd->shade.val =
11697            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
11698         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11699      }
11700    else
11701      {
11702         bd->shade.val =
11703            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11704         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11705      }
11706
11707    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
11708    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
11709    else if (bd->shade.val > .999)
11710      bd->shade.val = 1.0;
11711
11712    if (bd->shade.dir == E_DIRECTION_UP)
11713      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11714    else if (bd->shade.dir == E_DIRECTION_DOWN)
11715      {
11716         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11717         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
11718         bd->changes.pos = 1;
11719      }
11720    else if (bd->shade.dir == E_DIRECTION_LEFT)
11721      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11722    else if (bd->shade.dir == E_DIRECTION_RIGHT)
11723      {
11724         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11725         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
11726         bd->changes.pos = 1;
11727      }
11728
11729    if ((bd->shaped) || (bd->client.shaped))
11730      {
11731         bd->need_shape_merge = 1;
11732         bd->need_shape_export = 1;
11733      }
11734    if (bd->shaped_input)
11735      {
11736         bd->need_shape_merge = 1;
11737      }
11738    bd->changes.size = 1;
11739    bd->changed = 1;
11740
11741    /* we're done */
11742    if (val == 1)
11743      {
11744         E_Event_Border_Resize *ev;
11745
11746         bd->shading = 0;
11747         bd->shaded = !(bd->shaded);
11748         bd->changes.size = 1;
11749         bd->changes.shaded = 1;
11750         bd->changes.shading = 1;
11751         bd->changed = 1;
11752         bd->shade.anim = NULL;
11753
11754         if (bd->shaded)
11755           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
11756         else
11757           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
11758         edje_object_message_signal_process(bd->bg_object);
11759         e_border_frame_recalc(bd);
11760
11761         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
11762         ev = E_NEW(E_Event_Border_Resize, 1);
11763         ev->border = bd;
11764         e_object_ref(E_OBJECT(bd));
11765 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
11766         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
11767         return ECORE_CALLBACK_CANCEL;
11768      }
11769    return ECORE_CALLBACK_RENEW;
11770 }
11771
11772 static void
11773 _e_border_event_border_resize_free(void *data __UNUSED__,
11774                                    void      *ev)
11775 {
11776    E_Event_Border_Resize *e;
11777
11778    e = ev;
11779 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
11780    e_object_unref(E_OBJECT(e->border));
11781    E_FREE(e);
11782 }
11783
11784 static void
11785 _e_border_event_border_move_free(void *data __UNUSED__,
11786                                  void      *ev)
11787 {
11788    E_Event_Border_Move *e;
11789
11790    e = ev;
11791 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
11792    e_object_unref(E_OBJECT(e->border));
11793    E_FREE(e);
11794 }
11795
11796 static void
11797 _e_border_event_border_add_free(void *data __UNUSED__,
11798                                 void      *ev)
11799 {
11800    E_Event_Border_Add *e;
11801
11802    e = ev;
11803 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
11804    e_object_unref(E_OBJECT(e->border));
11805    E_FREE(e);
11806 }
11807
11808 static void
11809 _e_border_event_border_remove_free(void *data __UNUSED__,
11810                                    void      *ev)
11811 {
11812    E_Event_Border_Remove *e;
11813
11814    e = ev;
11815 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
11816    e_object_unref(E_OBJECT(e->border));
11817    E_FREE(e);
11818 }
11819
11820 static void
11821 _e_border_event_border_show_free(void *data __UNUSED__,
11822                                  void      *ev)
11823 {
11824    E_Event_Border_Show *e;
11825
11826    e = ev;
11827 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
11828    e_object_unref(E_OBJECT(e->border));
11829    E_FREE(e);
11830 }
11831
11832 static void
11833 _e_border_event_border_hide_free(void *data __UNUSED__,
11834                                  void      *ev)
11835 {
11836    E_Event_Border_Hide *e;
11837
11838    e = ev;
11839 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
11840    e_object_unref(E_OBJECT(e->border));
11841    E_FREE(e);
11842 }
11843
11844 static void
11845 _e_border_event_border_iconify_free(void *data __UNUSED__,
11846                                     void      *ev)
11847 {
11848    E_Event_Border_Iconify *e;
11849
11850    e = ev;
11851 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
11852    e_object_unref(E_OBJECT(e->border));
11853    E_FREE(e);
11854 }
11855
11856 static void
11857 _e_border_event_border_uniconify_free(void *data __UNUSED__,
11858                                       void      *ev)
11859 {
11860    E_Event_Border_Uniconify *e;
11861
11862    e = ev;
11863 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
11864    e_object_unref(E_OBJECT(e->border));
11865    E_FREE(e);
11866 }
11867
11868 static void
11869 _e_border_event_border_stick_free(void *data __UNUSED__,
11870                                   void      *ev)
11871 {
11872    E_Event_Border_Stick *e;
11873
11874    e = ev;
11875 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
11876    e_object_unref(E_OBJECT(e->border));
11877    E_FREE(e);
11878 }
11879
11880 static void
11881 _e_border_event_border_unstick_free(void *data __UNUSED__,
11882                                     void      *ev)
11883 {
11884    E_Event_Border_Unstick *e;
11885
11886    e = ev;
11887 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
11888    e_object_unref(E_OBJECT(e->border));
11889    E_FREE(e);
11890 }
11891
11892 static void
11893 _e_border_event_border_zone_set_free(void *data __UNUSED__,
11894                                      void      *ev)
11895 {
11896    E_Event_Border_Zone_Set *e;
11897
11898    e = ev;
11899 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
11900    e_object_unref(E_OBJECT(e->border));
11901    e_object_unref(E_OBJECT(e->zone));
11902    E_FREE(e);
11903 }
11904
11905 static void
11906 _e_border_event_border_desk_set_free(void *data __UNUSED__,
11907                                      void      *ev)
11908 {
11909    E_Event_Border_Desk_Set *e;
11910
11911    e = ev;
11912 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
11913    e_object_unref(E_OBJECT(e->border));
11914    e_object_unref(E_OBJECT(e->desk));
11915    E_FREE(e);
11916 }
11917
11918 static void
11919 _e_border_event_border_stack_free(void *data __UNUSED__,
11920                                   void      *ev)
11921 {
11922    E_Event_Border_Stack *e;
11923
11924    e = ev;
11925 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
11926    e_object_unref(E_OBJECT(e->border));
11927    if (e->stack)
11928      {
11929 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
11930           e_object_unref(E_OBJECT(e->stack));
11931      }
11932    E_FREE(e);
11933 }
11934
11935 static void
11936 _e_border_event_border_icon_change_free(void *data __UNUSED__,
11937                                         void      *ev)
11938 {
11939    E_Event_Border_Icon_Change *e;
11940
11941    e = ev;
11942 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
11943    e_object_unref(E_OBJECT(e->border));
11944    E_FREE(e);
11945 }
11946
11947 static void
11948 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
11949                                           void      *ev)
11950 {
11951    E_Event_Border_Urgent_Change *e;
11952
11953    e = ev;
11954    e_object_unref(E_OBJECT(e->border));
11955    E_FREE(e);
11956 }
11957
11958 static void
11959 _e_border_event_border_focus_in_free(void *data __UNUSED__,
11960                                      void      *ev)
11961 {
11962    E_Event_Border_Focus_In *e;
11963
11964    e = ev;
11965    e_object_unref(E_OBJECT(e->border));
11966    E_FREE(e);
11967 }
11968
11969 static void
11970 _e_border_event_border_focus_out_free(void *data __UNUSED__,
11971                                       void      *ev)
11972 {
11973    E_Event_Border_Focus_Out *e;
11974
11975    e = ev;
11976    e_object_unref(E_OBJECT(e->border));
11977    E_FREE(e);
11978 }
11979
11980 static void
11981 _e_border_event_border_property_free(void *data __UNUSED__,
11982                                      void      *ev)
11983 {
11984    E_Event_Border_Property *e;
11985
11986    e = ev;
11987    e_object_unref(E_OBJECT(e->border));
11988    E_FREE(e);
11989 }
11990
11991 static void
11992 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
11993                                        void      *ev)
11994 {
11995    E_Event_Border_Fullscreen *e;
11996
11997    e = ev;
11998 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
11999    e_object_unref(E_OBJECT(e->border));
12000    E_FREE(e);
12001 }
12002
12003 static void
12004 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
12005                                          void      *ev)
12006 {
12007    E_Event_Border_Unfullscreen *e;
12008
12009    e = ev;
12010 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
12011    e_object_unref(E_OBJECT(e->border));
12012    E_FREE(e);
12013 }
12014
12015 #ifdef _F_ZONE_WINDOW_ROTATION_
12016 static void
12017 _e_border_event_border_rotation_change_begin_free(void *data __UNUSED__,
12018                                                   void      *ev)
12019 {
12020    E_Event_Border_Rotation_Change_Begin *e;
12021    e = ev;
12022    e_object_unref(E_OBJECT(e->border));
12023    E_FREE(e);
12024 }
12025
12026 static void
12027 _e_border_event_border_rotation_change_cancel_free(void *data __UNUSED__,
12028                                                    void      *ev)
12029 {
12030    E_Event_Border_Rotation_Change_Cancel *e;
12031    e = ev;
12032    e_object_unref(E_OBJECT(e->border));
12033    E_FREE(e);
12034 }
12035
12036 static void
12037 _e_border_event_border_rotation_change_end_free(void *data __UNUSED__,
12038                                                 void      *ev)
12039 {
12040    E_Event_Border_Rotation_Change_End *e;
12041    e = ev;
12042    e_object_unref(E_OBJECT(e->border));
12043    E_FREE(e);
12044 }
12045
12046 static void
12047 _e_border_event_border_rotation_change_begin_send(E_Border *bd)
12048 {
12049    E_Event_Border_Rotation_Change_Begin *ev = NULL;
12050    ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
12051    if (ev)
12052      {
12053         ev->border = bd;
12054         e_object_ref(E_OBJECT(bd));
12055         ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_BEGIN,
12056                         ev,
12057                         _e_border_event_border_rotation_change_begin_free,
12058                         NULL);
12059      }
12060 }
12061 #endif
12062
12063 static void
12064 _e_border_zone_update(E_Border *bd)
12065 {
12066    E_Container *con;
12067    Eina_List *l;
12068    E_Zone *zone;
12069
12070    /* still within old zone - leave it there */
12071    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12072                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
12073 #if _F_BORDER_CLIP_TO_ZONE_
12074      {
12075         _e_border_shape_input_clip_to_zone(bd);
12076         return;
12077      }
12078 #else
12079      return;
12080 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12081    /* find a new zone */
12082    con = bd->zone->container;
12083    EINA_LIST_FOREACH(con->zones, l, zone)
12084      {
12085         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12086                          zone->x, zone->y, zone->w, zone->h))
12087           {
12088              e_border_zone_set(bd, zone);
12089 #if _F_BORDER_CLIP_TO_ZONE_
12090              _e_border_shape_input_clip_to_zone(bd);
12091 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12092              return;
12093           }
12094      }
12095 }
12096
12097 static int
12098 _e_border_resize_begin(E_Border *bd)
12099 {
12100    int ret;
12101
12102    if (!bd->lock_user_stacking)
12103      {
12104         if (e_config->border_raise_on_mouse_action)
12105           e_border_raise(bd);
12106      }
12107    if ((bd->shaded) || (bd->shading) ||
12108        (bd->fullscreen) || (bd->lock_user_size))
12109      return 0;
12110
12111    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12112      ret = e_grabinput_get(bd->win, 0, bd->win);
12113    else
12114      ret = e_grabinput_get(bd->win, 0, 0);
12115
12116    if (grabbed && !ret)
12117      {
12118         grabbed = 0;
12119         return 0;
12120      }
12121
12122    if (bd->client.netwm.sync.request)
12123      {
12124         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12125         bd->client.netwm.sync.serial = 1;
12126         bd->client.netwm.sync.wait = 0;
12127         bd->client.netwm.sync.send_time = ecore_loop_time_get();
12128      }
12129
12130    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
12131
12132    bdresize = bd;
12133    return 1;
12134 }
12135
12136 static int
12137 _e_border_resize_end(E_Border *bd)
12138 {
12139    if (grabbed)
12140      {
12141         e_grabinput_release(bd->win, bd->win);
12142         grabbed = 0;
12143      }
12144    if (bd->client.netwm.sync.alarm)
12145      {
12146         E_Border_Pending_Move_Resize *pnd;
12147
12148         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12149         bd->client.netwm.sync.alarm = 0;
12150         /* resize to last geometry if sync alarm for it was not yet handled */
12151         if (bd->pending_move_resize)
12152           {
12153              bd->changed = 1;
12154              bd->changes.pos = 1;
12155              bd->changes.size = 1;
12156              _e_border_client_move_resize_send(bd);
12157           }
12158
12159         EINA_LIST_FREE(bd->pending_move_resize, pnd)
12160           E_FREE(pnd);
12161      }
12162
12163    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
12164
12165    bdresize = NULL;
12166
12167    /* If this border was maximized, we need to unset Maximized state or
12168     * on restart, E still thinks it's maximized */
12169    if (bd->maximized != E_MAXIMIZE_NONE)
12170      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
12171                                   bd->maximized & E_MAXIMIZE_NONE);
12172    return 1;
12173 }
12174
12175 static void
12176 _e_border_resize_update(E_Border *bd)
12177 {
12178    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
12179 }
12180
12181 static int
12182 _e_border_move_begin(E_Border *bd)
12183 {
12184    int ret;
12185    if (!bd->lock_user_stacking)
12186      {
12187         if (e_config->border_raise_on_mouse_action)
12188           e_border_raise(bd);
12189      }
12190    if ((bd->fullscreen) || (bd->lock_user_location))
12191      return 0;
12192
12193    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12194      ret = e_grabinput_get(bd->win, 0, bd->win);
12195    else
12196      ret = e_grabinput_get(bd->win, 0, 0);
12197
12198    if (grabbed && !ret)
12199      {
12200         grabbed = 0;
12201         return 0;
12202      }
12203 #if 0
12204    if (bd->client.netwm.sync.request)
12205      {
12206         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12207         bd->client.netwm.sync.serial = 0;
12208         bd->client.netwm.sync.wait = 0;
12209         bd->client.netwm.sync.time = ecore_loop_time_get();
12210      }
12211 #endif
12212    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
12213
12214    bdmove = bd;
12215    return 1;
12216 }
12217
12218 static int
12219 _e_border_move_end(E_Border *bd)
12220 {
12221    if (grabbed)
12222      {
12223         e_grabinput_release(bd->win, bd->win);
12224         grabbed = 0;
12225      }
12226 #if 0
12227    if (bd->client.netwm.sync.alarm)
12228      {
12229         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12230         bd->client.netwm.sync.alarm = 0;
12231      }
12232 #endif
12233    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
12234
12235    bdmove = NULL;
12236    return 1;
12237 }
12238
12239 static void
12240 _e_border_move_update(E_Border *bd)
12241 {
12242    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
12243 }
12244
12245 static Eina_Bool
12246 _e_border_cb_ping_poller(void *data)
12247 {
12248    E_Border *bd;
12249
12250    bd = data;
12251    if (bd->ping_ok)
12252      {
12253         if (bd->hung)
12254           {
12255              bd->hung = 0;
12256              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
12257              if (bd->kill_timer)
12258                {
12259                   ecore_timer_del(bd->kill_timer);
12260                   bd->kill_timer = NULL;
12261                }
12262           }
12263      }
12264    else
12265      {
12266         /* if time between last ping and now is greater
12267          * than half the ping interval... */
12268         if ((ecore_loop_time_get() - bd->ping) >
12269             ((e_config->ping_clients_interval *
12270               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
12271           {
12272              if (!bd->hung)
12273                {
12274                   bd->hung = 1;
12275                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
12276                   /* FIXME: if below dialog is up - hide it now */
12277                }
12278              if (bd->delete_requested)
12279                {
12280                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
12281                   e_border_act_kill_begin(bd);
12282                }
12283           }
12284      }
12285    bd->ping_poller = NULL;
12286    e_border_ping(bd);
12287    return ECORE_CALLBACK_CANCEL;
12288 }
12289
12290 static Eina_Bool
12291 _e_border_cb_kill_timer(void *data)
12292 {
12293    E_Border *bd;
12294
12295    bd = data;
12296 // dont wait until it's hung -
12297 //   if (bd->hung)
12298 //     {
12299         if (bd->client.netwm.pid > 1)
12300           kill(bd->client.netwm.pid, SIGKILL);
12301 //     }
12302    bd->kill_timer = NULL;
12303    return ECORE_CALLBACK_CANCEL;
12304 }
12305
12306 static void
12307 _e_border_pointer_resize_begin(E_Border *bd)
12308 {
12309    switch (bd->resize_mode)
12310      {
12311       case RESIZE_TL:
12312         e_pointer_type_push(bd->pointer, bd, "resize_tl");
12313         break;
12314
12315       case RESIZE_T:
12316         e_pointer_type_push(bd->pointer, bd, "resize_t");
12317         break;
12318
12319       case RESIZE_TR:
12320         e_pointer_type_push(bd->pointer, bd, "resize_tr");
12321         break;
12322
12323       case RESIZE_R:
12324         e_pointer_type_push(bd->pointer, bd, "resize_r");
12325         break;
12326
12327       case RESIZE_BR:
12328         e_pointer_type_push(bd->pointer, bd, "resize_br");
12329         break;
12330
12331       case RESIZE_B:
12332         e_pointer_type_push(bd->pointer, bd, "resize_b");
12333         break;
12334
12335       case RESIZE_BL:
12336         e_pointer_type_push(bd->pointer, bd, "resize_bl");
12337         break;
12338
12339       case RESIZE_L:
12340         e_pointer_type_push(bd->pointer, bd, "resize_l");
12341         break;
12342      }
12343 }
12344
12345 static void
12346 _e_border_pointer_resize_end(E_Border *bd)
12347 {
12348    switch (bd->resize_mode)
12349      {
12350       case RESIZE_TL:
12351         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
12352         break;
12353
12354       case RESIZE_T:
12355         e_pointer_type_pop(bd->pointer, bd, "resize_t");
12356         break;
12357
12358       case RESIZE_TR:
12359         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
12360         break;
12361
12362       case RESIZE_R:
12363         e_pointer_type_pop(bd->pointer, bd, "resize_r");
12364         break;
12365
12366       case RESIZE_BR:
12367         e_pointer_type_pop(bd->pointer, bd, "resize_br");
12368         break;
12369
12370       case RESIZE_B:
12371         e_pointer_type_pop(bd->pointer, bd, "resize_b");
12372         break;
12373
12374       case RESIZE_BL:
12375         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
12376         break;
12377
12378       case RESIZE_L:
12379         e_pointer_type_pop(bd->pointer, bd, "resize_l");
12380         break;
12381      }
12382 }
12383
12384 static void
12385 _e_border_pointer_move_begin(E_Border *bd)
12386 {
12387    e_pointer_type_push(bd->pointer, bd, "move");
12388 }
12389
12390 static void
12391 _e_border_pointer_move_end(E_Border *bd)
12392 {
12393    e_pointer_type_pop(bd->pointer, bd, "move");
12394 }
12395
12396 static Eina_List *_e_border_hooks = NULL;
12397 static int _e_border_hooks_delete = 0;
12398 static int _e_border_hooks_walking = 0;
12399
12400 static void
12401 _e_border_hooks_clean(void)
12402 {
12403    Eina_List *l, *ln;
12404    E_Border_Hook *bh;
12405
12406    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
12407      {
12408         if (bh->delete_me)
12409           {
12410              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
12411              free(bh);
12412           }
12413      }
12414 }
12415
12416 static void
12417 _e_border_hook_call(E_Border_Hook_Point hookpoint,
12418                     void               *bd)
12419 {
12420    Eina_List *l;
12421    E_Border_Hook *bh;
12422
12423    _e_border_hooks_walking++;
12424    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
12425      {
12426         if (bh->delete_me) continue;
12427         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
12428      }
12429    _e_border_hooks_walking--;
12430    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
12431      _e_border_hooks_clean();
12432 }
12433
12434 EAPI E_Border_Hook *
12435 e_border_hook_add(E_Border_Hook_Point               hookpoint,
12436                   void                              (*func)(void *data,
12437                                               void *bd),
12438                   void                             *data)
12439 {
12440    E_Border_Hook *bh;
12441
12442    bh = E_NEW(E_Border_Hook, 1);
12443    if (!bh) return NULL;
12444    bh->hookpoint = hookpoint;
12445    bh->func = func;
12446    bh->data = data;
12447    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
12448    return bh;
12449 }
12450
12451 EAPI void
12452 e_border_hook_del(E_Border_Hook *bh)
12453 {
12454    bh->delete_me = 1;
12455    if (_e_border_hooks_walking == 0)
12456      {
12457         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
12458         free(bh);
12459      }
12460    else
12461      _e_border_hooks_delete++;
12462 }
12463
12464 EAPI void
12465 e_border_focus_track_freeze(void)
12466 {
12467    focus_track_frozen++;
12468 }
12469
12470 EAPI void
12471 e_border_focus_track_thaw(void)
12472 {
12473    focus_track_frozen--;
12474 }
12475
12476 EAPI E_Border *
12477 e_border_under_pointer_get(E_Desk   *desk,
12478                            E_Border *exclude)
12479 {
12480    E_Border *bd = NULL, *cbd;
12481    Eina_List *l;
12482    int x, y;
12483
12484    /* We need to ensure that we can get the container window for the
12485     * zone of either the given desk or the desk of the excluded
12486     * window, so return if neither is given */
12487    if (desk)
12488      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
12489    else if (exclude)
12490      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
12491    else
12492      return NULL;
12493
12494    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
12495      {
12496         if (!cbd) continue;
12497         /* If a border was specified which should be excluded from the list
12498          * (because it will be closed shortly for example), skip */
12499         if ((exclude) && (cbd == exclude)) continue;
12500         if ((desk) && (cbd->desk != desk)) continue;
12501         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
12502           continue;
12503         /* If the layer is higher, the position of the window is higher
12504          * (always on top vs always below) */
12505         if (!bd || (cbd->layer > bd->layer))
12506           {
12507              bd = cbd;
12508              break;
12509           }
12510      }
12511    return bd;
12512 }
12513
12514 static Eina_Bool
12515 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
12516 {
12517    if (warp_to)
12518      {
12519         int x, y;
12520         double spd;
12521
12522         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
12523         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
12524             (y - warp_y) > 5 || (y - warp_y) < -5)
12525           {
12526              /* User moved the mouse, so stop warping */
12527              warp_to = 0;
12528              goto cleanup;
12529           }
12530
12531         /* We just use the same warp speed as configured
12532          * for the windowlist */
12533         spd = e_config->winlist_warp_speed;
12534         x = warp_x;
12535         y = warp_y;
12536         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12537         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12538         if (warp_x == x && warp_y == y)
12539           {
12540              warp_x = warp_to_x;
12541              warp_y = warp_to_y;
12542              warp_to = 0;
12543              goto cleanup;
12544           }
12545         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12546         return ECORE_CALLBACK_RENEW;
12547      }
12548  cleanup:
12549    ecore_timer_del(warp_timer);
12550    warp_timer = NULL;
12551    return ECORE_CALLBACK_CANCEL;
12552 }
12553
12554 EAPI int
12555 e_border_pointer_warp_to_center(E_Border *bd)
12556 {
12557    int x, y;
12558
12559    /* Do not slide pointer when disabled (probably breaks focus
12560     * on sloppy/mouse focus but requested by users). */
12561    if (!e_config->pointer_slide) return 0;
12562    /* Only warp the pointer if it is not already in the area of
12563     * the given border */
12564    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12565    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12566        (y >= bd->y) && (y <= (bd->y + bd->h)))
12567      return 0;
12568
12569    warp_to_x = bd->x + (bd->w / 2);
12570    if (warp_to_x < (bd->zone->x + 1))
12571      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12572    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12573      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12574
12575    warp_to_y = bd->y + (bd->h / 2);
12576    if (warp_to_y < (bd->zone->y + 1))
12577      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12578    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12579      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12580
12581    warp_to = 1;
12582    warp_to_win = bd->zone->container->win;
12583    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12584    if (!warp_timer)
12585      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12586    return 1;
12587 }
12588
12589 EAPI void
12590 e_border_comp_hidden_set(E_Border *bd,
12591                          Eina_Bool hidden)
12592 {
12593    E_Border *tmp;
12594    Eina_List *l;
12595
12596    E_OBJECT_CHECK(bd);
12597    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12598
12599    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12600      {
12601        if (hidden)
12602          ecore_x_window_hide(tmp->win);
12603        else
12604          ecore_x_window_show(tmp->win);
12605      }
12606
12607    if (bd->comp_hidden == hidden) return;
12608
12609    bd->comp_hidden = hidden;
12610
12611    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12612      {
12613         ecore_x_composite_window_events_disable(bd->win);
12614         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12615      }
12616    else
12617      {
12618         _e_border_shape_input_rectangle_set(bd);
12619         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12620      }
12621 }
12622
12623 EAPI void
12624 e_border_tmp_input_hidden_push(E_Border *bd)
12625 {
12626    E_Border *tmp;
12627    Eina_List *l;
12628
12629    E_OBJECT_CHECK(bd);
12630    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12631
12632    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12633      e_border_tmp_input_hidden_push(tmp);
12634
12635    bd->tmp_input_hidden++;
12636    if (bd->tmp_input_hidden != 1) return;
12637
12638    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12639      {
12640         ecore_x_composite_window_events_disable(bd->win);
12641         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12642      }
12643    else
12644      {
12645         _e_border_shape_input_rectangle_set(bd);
12646         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12647      }
12648 }
12649
12650 EAPI void
12651 e_border_tmp_input_hidden_pop(E_Border *bd)
12652 {
12653    E_Border *tmp;
12654    Eina_List *l;
12655
12656    E_OBJECT_CHECK(bd);
12657    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12658
12659    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12660      e_border_tmp_input_hidden_pop(tmp);
12661
12662    bd->tmp_input_hidden--;
12663    if (bd->tmp_input_hidden != 0) return;
12664
12665    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12666      {
12667         ecore_x_composite_window_events_disable(bd->win);
12668         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12669      }
12670    else
12671      {
12672         _e_border_shape_input_rectangle_set(bd);
12673         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12674      }
12675 }
12676
12677 EAPI void
12678 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
12679 {
12680    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
12681        ((bd->parent) &&
12682         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
12683          ((bd->parent->focused) &&
12684           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
12685        (just_do_it))
12686      {
12687         if (bd->iconic)
12688           {
12689              if (e_config->clientlist_warp_to_iconified_desktop == 1)
12690                e_desk_show(bd->desk);
12691              
12692              if (!bd->lock_user_iconify)
12693                e_border_uniconify(bd);
12694           }
12695         if ((!bd->iconic) && (!bd->sticky))
12696           e_desk_show(bd->desk);
12697         if (!bd->lock_user_stacking) e_border_raise(bd);
12698         if (!bd->lock_focus_out)
12699           {
12700              /* XXX ooffice does send this request for
12701               config dialogs when the main window gets focus.
12702               causing the pointer to jump back and forth.  */
12703              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
12704                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
12705                ecore_x_pointer_warp(bd->zone->container->win,
12706                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
12707              e_border_focus_set(bd, 1, 1);
12708           }
12709      }
12710 }
12711 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/