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