When keyboard needs to rotate in unmap state,
[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
3768    if (e_config->deiconify_approve)
3769      {
3770         if (!e_object_is_del(E_OBJECT(bd)))
3771           {
3772              bd->client.e.state.deiconify_approve.pending_job = NULL;
3773
3774              ELBF(ELBT_BD, 0, bd->client.win,
3775                   "SEND DEICONIFY_APPROVE. (PENDING_END) ancestor:%x",
3776                   bd->client.win);
3777
3778              ecore_x_client_message32_send(bd->client.win,
3779                                            ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3780                                            ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3781                                            bd->client.win, 0, 0, 0, 0);
3782
3783              bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
3784           }
3785      }
3786 }
3787
3788 static void
3789 _e_border_deiconify_approve_send(E_Border *bd, E_Border *bd_ancestor, Eina_Bool pending_ancestor)
3790 {
3791    if (!bd || !bd_ancestor) return;
3792
3793    if (e_config->deiconify_approve)
3794      {
3795         if (e_config->transient.iconify)
3796           {
3797              Eina_List *l;
3798              E_Border *child;
3799              Eina_List *list = _e_border_sub_borders_new(bd);
3800              EINA_LIST_FOREACH(list, l, child)
3801                {
3802                   Eina_Bool pending = EINA_FALSE;
3803                   Eina_Bool p = EINA_FALSE;
3804
3805 #ifdef _F_ZONE_WINDOW_ROTATION_
3806                   if ((e_config->wm_win_rotation) &&
3807                       ((child->client.e.state.rot.support) ||
3808                        (child->client.e.state.rot.app_set)))
3809                     {
3810                        ELB(ELBT_ROT, "CHECK_DEICONIFY CHILD", child->client.win);
3811                        int rotation = _e_border_rotation_angle_get(bd);
3812                        if (rotation != -1) _e_border_rotation_set_internal(bd, rotation, &pending);
3813                     }
3814 #endif
3815                   if ((pending_ancestor) || (pending)) p = EINA_TRUE;
3816
3817                   _e_border_deiconify_approve_send(child, bd_ancestor, p);
3818                   if (child->client.e.state.deiconify_approve.support)
3819                     {
3820                        if (p)
3821                          {
3822                             ELBF(ELBT_BD, 0, child->client.win,
3823                                  "SEND DEICONIFY_APPROVE. ancestor:%x pending(%d,%d)",
3824                                  bd_ancestor->client.win,
3825                                  pending_ancestor, pending);
3826
3827                             ecore_x_client_message32_send(child->client.win,
3828                                                           ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3829                                                           ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3830                                                           child->client.win, 0, 0, 0, 0);
3831                             child->client.e.state.deiconify_approve.ancestor = bd_ancestor;
3832                             bd_ancestor->client.e.state.deiconify_approve.req_list = eina_list_append(bd_ancestor->client.e.state.deiconify_approve.req_list, child);
3833                          }
3834                        else
3835                          {
3836                             /* queue a deiconify send job to give the chance to other jobs */
3837                             ELBF(ELBT_BD, 0, child->client.win,
3838                                  "SEND DEICONIFY_APPROVE. (PENDING) ancestor:%x",
3839                                  bd_ancestor->client.win);
3840                             child->client.e.state.deiconify_approve.pending_job = ecore_job_add(_e_border_deiconify_approve_send_pending_end, child);
3841                          }
3842                     }
3843                }
3844              eina_list_free(list);
3845           }
3846      }
3847 }
3848
3849 static void
3850 _e_border_deiconify_approve_send_all_transient(E_Border *bd)
3851 {
3852    Eina_Bool pending = EINA_FALSE;
3853
3854    if (e_config->deiconify_approve)
3855      {
3856 #ifdef _F_ZONE_WINDOW_ROTATION_
3857         if ((e_config->wm_win_rotation) &&
3858             ((bd->client.e.state.rot.support) ||
3859              (bd->client.e.state.rot.app_set)))
3860           {
3861              ELB(ELBT_ROT, "CHECK_DEICONIFY", bd->client.win);
3862              int rotation = _e_border_rotation_angle_get(bd);
3863              if (rotation != -1) _e_border_rotation_set_internal(bd, rotation, &pending);
3864           }
3865 #endif
3866
3867         if (e_config->transient.iconify)
3868           {
3869              _e_border_deiconify_approve_send(bd, bd, pending);
3870           }
3871
3872         if (bd->client.e.state.deiconify_approve.support)
3873           {
3874              if (!pending)
3875                {
3876                   ELBF(ELBT_BD, 0, bd->client.win, "SEND DEICONIFY_APPROVE.");
3877                   ecore_x_client_message32_send(bd->client.win,
3878                                                 ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3879                                                 ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3880                                                 bd->client.win, 0, 0, 0, 0);
3881                   bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
3882                }
3883              else
3884                {
3885                   /* queue a deiconify send job to give the chance to other jobs */
3886                   ELBF(ELBT_BD, 0, bd->client.win, "SEND DEICONIFY_APPROVE. (PENDING)");
3887                   bd->client.e.state.deiconify_approve.pending_job = ecore_job_add(_e_border_deiconify_approve_send_pending_end, bd);
3888                }
3889           }
3890      }
3891 }
3892 #endif
3893
3894 EAPI void
3895 e_border_uniconify(E_Border *bd)
3896 {
3897    E_Desk *desk;
3898    E_Event_Border_Uniconify *ev;
3899    unsigned int iconic;
3900
3901    E_OBJECT_CHECK(bd);
3902    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3903
3904 #ifdef _F_DEICONIFY_APPROVE_
3905    if (e_config->deiconify_approve)
3906      {
3907         if (bd->client.e.state.deiconify_approve.support)
3908           {
3909              if (bd->client.e.state.deiconify_approve.wait_timer)
3910                {
3911                   ELB(ELBT_BD, "DEICONIFY_APPROVE WAIT_TIMER is already running", bd->client.win);
3912                   return;
3913                }
3914              if (bd->client.e.state.deiconify_approve.render_done == 0)
3915                {
3916                   ELB(ELBT_BD, "DEICONIFY_APPROVE to all transient", bd->client.win);
3917                   _e_border_deiconify_approve_send_all_transient(bd);
3918                   return;
3919                }
3920           }
3921         bd->client.e.state.deiconify_approve.render_done = 0;
3922      }
3923 #endif
3924
3925 #if _F_ZONE_WINDOW_ROTATION_
3926    if (!bd->client.win)
3927      {
3928         ELB(ELBT_DFT, "ERR! obj is already deleted", bd->client.win);
3929         return;
3930      }
3931 #endif
3932
3933    if (bd->shading) return;
3934    ecore_x_window_shadow_tree_flush();
3935    e_border_show(bd);
3936    if (bd->iconic)
3937      {
3938         bd->iconic = 0;
3939         if (bd->fullscreen) bd->desk->fullscreen_borders++;
3940         desk = e_desk_current_get(bd->desk->zone);
3941 #ifdef _F_USE_EXTENDED_ICONIFY_
3942         if (e_manager_comp_evas_get(bd->zone->container->manager))
3943           {
3944              if (bd->await_hide_event > 0)
3945                bd->await_hide_event--;
3946           }
3947 #endif
3948         e_border_desk_set(bd, desk);
3949         e_border_raise(bd);
3950         edje_object_signal_emit(bd->bg_object, "e,action,uniconify", "e");
3951      }
3952    iconic = 0;
3953    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
3954
3955    ev = E_NEW(E_Event_Border_Uniconify, 1);
3956    ev->border = bd;
3957    e_object_ref(E_OBJECT(bd));
3958 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_uniconify_event");
3959    ecore_event_add(E_EVENT_BORDER_UNICONIFY, ev, _e_border_event_border_uniconify_free, NULL);
3960
3961    if (e_config->transient.iconify)
3962      {
3963         Eina_List *l;
3964         E_Border *child;
3965         Eina_List *list = _e_border_sub_borders_new(bd);
3966
3967         EINA_LIST_FOREACH(list, l, child)
3968           {
3969              e_border_uniconify(child);
3970           }
3971         eina_list_free(list);
3972      }
3973    e_remember_update(bd);
3974 }
3975
3976 EAPI void
3977 e_border_stick(E_Border *bd)
3978 {
3979    E_Event_Border_Stick *ev;
3980
3981    E_OBJECT_CHECK(bd);
3982    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3983    if (bd->sticky) return;
3984    bd->sticky = 1;
3985    e_hints_window_sticky_set(bd, 1);
3986    e_border_show(bd);
3987
3988    if (e_config->transient.desktop)
3989      {
3990         Eina_List *l;
3991         E_Border *child;
3992         Eina_List *list = _e_border_sub_borders_new(bd);
3993
3994         EINA_LIST_FOREACH(list, l, child)
3995           {
3996              child->sticky = 1;
3997              e_hints_window_sticky_set(child, 1);
3998              e_border_show(child);
3999           }
4000         eina_list_free(list);
4001      }
4002
4003    edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
4004    ev = E_NEW(E_Event_Border_Stick, 1);
4005    ev->border = bd;
4006    e_object_ref(E_OBJECT(bd));
4007 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_stick_event");
4008    ecore_event_add(E_EVENT_BORDER_STICK, ev, _e_border_event_border_stick_free, NULL);
4009    e_remember_update(bd);
4010 }
4011
4012 EAPI void
4013 e_border_unstick(E_Border *bd)
4014 {
4015    E_Event_Border_Unstick *ev;
4016
4017    E_OBJECT_CHECK(bd);
4018    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4019    /* Set the desk before we unstick the border */
4020    if (!bd->sticky) return;
4021    bd->sticky = 0;
4022    e_hints_window_sticky_set(bd, 0);
4023
4024    if (e_config->transient.desktop)
4025      {
4026         Eina_List *l;
4027         E_Border *child;
4028         Eina_List *list = _e_border_sub_borders_new(bd);
4029
4030         EINA_LIST_FOREACH(list, l, child)
4031           {
4032              child->sticky = 0;
4033              e_hints_window_sticky_set(child, 0);
4034           }
4035         eina_list_free(list);
4036      }
4037
4038    edje_object_signal_emit(bd->bg_object, "e,state,unsticky", "e");
4039    ev = E_NEW(E_Event_Border_Unstick, 1);
4040    ev->border = bd;
4041    e_object_ref(E_OBJECT(bd));
4042 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_unstick_event");
4043    ecore_event_add(E_EVENT_BORDER_UNSTICK, ev, _e_border_event_border_unstick_free, NULL);
4044
4045    e_border_desk_set(bd, e_desk_current_get(bd->zone));
4046    e_remember_update(bd);
4047 }
4048
4049 EAPI void
4050 e_border_pinned_set(E_Border *bd,
4051                     int       set)
4052 {
4053    int layer;
4054    int stacking;
4055
4056    if (bd)
4057      {
4058         bd->borderless = set;
4059         bd->user_skip_winlist = set;
4060         if (set)
4061           {
4062              layer = 50;
4063              stacking = E_STACKING_BELOW;
4064           }
4065         else
4066           {
4067              layer = 100;
4068              stacking = E_STACKING_NONE;
4069           }
4070
4071         e_border_layer_set(bd, layer);
4072         e_hints_window_stacking_set(bd, stacking);
4073
4074         bd->client.border.changed = 1;
4075         bd->changed = 1;
4076      }
4077 }
4078
4079 EAPI E_Border *
4080 e_border_find_by_client_window(Ecore_X_Window win)
4081 {
4082    E_Border *bd;
4083
4084    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4085    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4086        (bd->client.win == win))
4087      return bd;
4088    return NULL;
4089 }
4090
4091 EAPI E_Border *
4092 e_border_find_all_by_client_window(Ecore_X_Window win)
4093 {
4094    E_Border *bd;
4095
4096    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4097    if ((bd) && (bd->client.win == win))
4098      return bd;
4099    return NULL;
4100 }
4101
4102 EAPI E_Border *
4103 e_border_find_by_frame_window(Ecore_X_Window win)
4104 {
4105    E_Border *bd;
4106
4107    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4108    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4109        (bd->bg_win == win))
4110      return bd;
4111    return NULL;
4112 }
4113
4114 EAPI E_Border *
4115 e_border_find_by_window(Ecore_X_Window win)
4116 {
4117    E_Border *bd;
4118
4119    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4120    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4121        (bd->win == win))
4122      return bd;
4123    return NULL;
4124 }
4125
4126 EAPI E_Border *
4127 e_border_find_by_alarm(Ecore_X_Sync_Alarm al)
4128 {
4129    Eina_List *l;
4130    E_Border *bd;
4131
4132    EINA_LIST_FOREACH(borders, l, bd)
4133      {
4134         if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4135             (bd->client.netwm.sync.alarm == al))
4136           return bd;
4137      }
4138    return NULL;
4139 }
4140
4141 EAPI E_Border *
4142 e_border_focused_get(void)
4143 {
4144    return focused;
4145 }
4146
4147 static void
4148 _e_border_shape_input_rectangle_set(E_Border* bd)
4149 {
4150    if (!bd) return;
4151
4152    if ((bd->visible) && (bd->shaped_input))
4153      {
4154         Ecore_X_Rectangle rects[4];
4155         Ecore_X_Window twin, twin2;
4156         int x, y;
4157
4158         twin = ecore_x_window_override_new(bd->zone->container->scratch_win,
4159                                            0, 0, bd->w, bd->h);
4160         rects[0].x = 0;
4161         rects[0].y = 0;
4162         rects[0].width = bd->w;
4163         rects[0].height = bd->client_inset.t;
4164         rects[1].x = 0;
4165         rects[1].y = bd->client_inset.t;
4166         rects[1].width = bd->client_inset.l;
4167         rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
4168         rects[2].x = bd->w - bd->client_inset.r;
4169         rects[2].y = bd->client_inset.t;
4170         rects[2].width = bd->client_inset.r;
4171         rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
4172         rects[3].x = 0;
4173         rects[3].y = bd->h - bd->client_inset.b;
4174         rects[3].width = bd->w;
4175         rects[3].height = bd->client_inset.b;
4176         ecore_x_window_shape_input_rectangles_set(twin, rects, 4);
4177
4178         twin2 = ecore_x_window_override_new
4179            (bd->zone->container->scratch_win, 0, 0,
4180                bd->w - bd->client_inset.l - bd->client_inset.r,
4181                bd->h - bd->client_inset.t - bd->client_inset.b);
4182         x = 0;
4183         y = 0;
4184         if ((bd->shading) || (bd->shaded))
4185           {
4186              if (bd->shade.dir == E_DIRECTION_UP)
4187                 y = bd->h - bd->client_inset.t - bd->client_inset.b -
4188                 bd->client.h;
4189              else if (bd->shade.dir == E_DIRECTION_LEFT)
4190                 x = bd->w - bd->client_inset.l - bd->client_inset.r -
4191                 bd->client.w;
4192           }
4193         ecore_x_window_shape_input_window_set_xy(twin2, bd->client.win,
4194                                                  x, y);
4195         ecore_x_window_shape_input_rectangle_clip(twin2, 0, 0,
4196                                                   bd->w - bd->client_inset.l - bd->client_inset.r,
4197                                                   bd->h - bd->client_inset.t - bd->client_inset.b);
4198         ecore_x_window_shape_input_window_add_xy(twin, twin2,
4199                                                  bd->client_inset.l,
4200                                                  bd->client_inset.t);
4201         ecore_x_window_shape_input_window_set(bd->win, twin);
4202         ecore_x_window_free(twin2);
4203         ecore_x_window_free(twin);
4204      }
4205    else
4206      {
4207         if (bd->visible) // not shaped input
4208           {
4209              if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
4210                 ecore_x_composite_window_events_enable(bd->win);
4211              else
4212                 ecore_x_composite_window_events_disable(bd->win);
4213           }
4214         else
4215           {
4216              if (!e_manager_comp_evas_get(bd->zone->container->manager))
4217                 ecore_x_composite_window_events_enable(bd->win);
4218              else
4219                 ecore_x_composite_window_events_disable(bd->win);
4220           }
4221      }
4222 }
4223
4224 EAPI void
4225 e_border_idler_before(void)
4226 {
4227    Eina_List *ml, *cl;
4228    E_Manager *man;
4229    E_Container *con;
4230
4231    if (!borders)
4232      return;
4233
4234    EINA_LIST_FOREACH(e_manager_list(), ml, man)
4235      {
4236         EINA_LIST_FOREACH(man->containers, cl, con)
4237           {
4238              E_Border_List *bl;
4239              E_Border *bd;
4240
4241              // pass 1 - eval0. fetch properties on new or on change and
4242              // call hooks to decide what to do - maybe move/resize
4243              bl = e_container_border_list_last(con);
4244              while ((bd = e_container_border_list_prev(bl)))
4245                {
4246                   if (bd->changed) _e_border_eval0(bd);
4247                }
4248              e_container_border_list_free(bl);
4249
4250              // layout hook - this is where a hook gets to figure out what to
4251              // do if anything.
4252              _e_border_container_layout_hook(con);
4253
4254              // pass 2 - show windows needing show
4255              bl = e_container_border_list_last(con);
4256              while ((bd = e_container_border_list_prev(bl)))
4257                {
4258                   if ((bd->changes.visible) && (bd->visible) &&
4259                       (!bd->new_client) && (!bd->changes.pos) &&
4260                       (!bd->changes.size))
4261                     {
4262                        _e_border_show(bd);
4263                        bd->changes.visible = 0;
4264                     }
4265                }
4266              e_container_border_list_free(bl);
4267
4268              // pass 3 - hide windows needing hide and eval (main eval)
4269              bl = e_container_border_list_first(con);
4270              while ((bd = e_container_border_list_next(bl)))
4271                {
4272                   if (e_object_is_del(E_OBJECT(bd))) continue;
4273
4274                   if ((bd->changes.visible) && (!bd->visible))
4275                     {
4276                        _e_border_hide(bd);
4277                        bd->changes.visible = 0;
4278                     }
4279
4280                   if (bd->changed) _e_border_eval(bd);
4281
4282                   if ((bd->changes.visible) && (bd->visible))
4283                     {
4284                        _e_border_show(bd);
4285                        bd->changes.visible = 0;
4286                     }
4287                }
4288              e_container_border_list_free(bl);
4289           }
4290      }
4291
4292    if (focus_next)
4293      {
4294         E_Border *bd = NULL, *bd2;
4295
4296         EINA_LIST_FREE(focus_next, bd2)
4297           if ((!bd) && (bd2->visible)) bd = bd2;
4298
4299         if (!bd)
4300           {
4301              /* TODO revert focus when lost here ? */
4302              return;
4303           }
4304 #if 0
4305         if (bd == focused)
4306           {
4307              /* already focused. but anyway dont be so strict, this
4308                 fcks up illume setting focus on internal windows */
4309              return;
4310           }
4311 #endif
4312         
4313         focus_time = ecore_x_current_time_get();
4314
4315         focusing = bd;
4316
4317         if ((bd->client.icccm.take_focus) &&
4318             (bd->client.icccm.accepts_focus))
4319           {
4320              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
4321              /* TODO what if the client didn't take focus ? */
4322           }
4323         else if (!bd->client.icccm.accepts_focus)
4324           {
4325              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
4326           }
4327         else if (!bd->client.icccm.take_focus)
4328           {
4329              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
4330              /* e_border_focus_set(bd, 1, 0); */
4331           }
4332      }
4333
4334 #ifdef _F_ZONE_WINDOW_ROTATION_
4335    if ((e_config->wm_win_rotation) &&
4336        (rot.fetch))
4337      {
4338         Ecore_X_Event_Client_Message *msg = NULL;
4339         Ecore_X_Atom t = 0;
4340         EINA_LIST_FREE(rot.msgs, msg)
4341           {
4342              t = msg->message_type;
4343              if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)
4344                {
4345                   if ((rot.vkbd_ctrl_win) &&
4346                       ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) &&
4347                       (rot.vkbd))
4348                     {
4349                        ELB(ELBT_BD, "GET KBD_ON_PREPARE_DONE", rot.vkbd_ctrl_win);
4350                        if (rot.vkbd_show_prepare_timer)
4351                          _e_border_vkbd_show(rot.vkbd);
4352                        else
4353                          ELB(ELBT_BD, "GET KBD_ON_PREPARE_DONE but skip", rot.vkbd_ctrl_win);
4354                     }
4355                }
4356              else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE)
4357                {
4358                   if ((rot.vkbd_ctrl_win) &&
4359                       ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) &&
4360                       (rot.vkbd))
4361                     {
4362                        ELB(ELBT_BD, "GET KBD_OFF_PREPARE_DONE", rot.vkbd_ctrl_win);
4363                        if (rot.vkbd_hide_prepare_timer)
4364                          {
4365                             _e_border_vkbd_hide(rot.vkbd);
4366                             rot.vkbd_hide_prepare_timer = NULL;
4367                             e_object_unref(E_OBJECT(rot.vkbd));
4368                          }
4369                        else
4370                          ELB(ELBT_BD, "GET KBD_OFF_PREPARE_DONE but skip", rot.vkbd_ctrl_win);
4371                     }
4372                }
4373              else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)
4374                {
4375                   rot.vkbd_ctrl_win = msg->data.l[0];
4376                   ELB(ELBT_BD, "SET KBD_CONTROL_WIN", rot.vkbd_ctrl_win);
4377                }
4378              else if (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE)
4379                {
4380                   if ((rot.vkbd_ctrl_win) &&
4381                       (rot.vkbd_ctrl_win == (Ecore_X_Window)msg->data.l[0]))
4382                     {
4383                        ELB(ELBT_ROT, "GET ROT_PREPARE_DONE", rot.vkbd_ctrl_win);
4384                        E_Manager *m = e_manager_current_get();
4385                        E_Zone *zone = NULL;
4386                        if (m) zone = e_util_zone_current_get(m);
4387                        if ((zone) && (rot.wait_prepare_done))
4388                          {
4389                             if (rot.list)
4390                               _e_border_rotation_change_request(zone);
4391                             else if (rot.async_list)
4392                               {
4393                                  _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
4394                                  rot.async_list = NULL;
4395                               }
4396                             if (rot.prepare_timer)
4397                               ecore_timer_del(rot.prepare_timer);
4398                             rot.prepare_timer = NULL;
4399                             rot.wait_prepare_done = EINA_FALSE;
4400                          }
4401                     }
4402                }
4403              E_FREE(msg);
4404           }
4405         rot.msgs = NULL;
4406         rot.fetch = EINA_FALSE;
4407      }
4408 #endif
4409 }
4410
4411 EAPI Eina_List *
4412 e_border_client_list(void)
4413 {
4414    /* FIXME: This should be a somewhat ordered list */
4415    return borders;
4416 }
4417
4418 static Ecore_X_Window action_input_win = 0;
4419 static E_Border *action_border = NULL;
4420 static Ecore_Event_Handler *action_handler_key = NULL;
4421 static Ecore_Event_Handler *action_handler_mouse = NULL;
4422 static Ecore_Timer *action_timer = NULL;
4423 static Ecore_X_Rectangle action_orig;
4424
4425 static void
4426 _e_border_show(E_Border *bd)
4427 {
4428    Eina_List *l;
4429    E_Border *tmp;
4430
4431    ecore_evas_show(bd->bg_ecore_evas);
4432
4433    if (bd->post_job)
4434      {
4435         bd->post_show = 1;
4436         return;
4437      }
4438
4439    if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
4440      {
4441         _e_border_shape_input_rectangle_set(bd);
4442         // not anymore
4443         //      ecore_x_composite_window_events_enable(bd->win);
4444         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
4445      }
4446
4447    ecore_x_window_show(bd->win);
4448
4449    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
4450      ecore_x_window_show(tmp->win);
4451 }
4452
4453 static void
4454 _e_border_hide(E_Border *bd)
4455 {
4456    E_Border *tmp;
4457    Eina_List *l;
4458
4459    if (!e_manager_comp_evas_get(bd->zone->container->manager))
4460      {
4461         ecore_x_window_hide(bd->win);
4462         ecore_evas_hide(bd->bg_ecore_evas);
4463
4464         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
4465           ecore_x_window_hide(tmp->win);
4466      }
4467    else
4468      {
4469         ecore_x_composite_window_events_disable(bd->win);
4470         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
4471      }
4472 }
4473
4474 static int
4475 _e_border_action_input_win_del(void)
4476 {
4477    if (!action_input_win)
4478      return 0;
4479
4480    e_grabinput_release(action_input_win, action_input_win);
4481    ecore_x_window_free(action_input_win);
4482    action_input_win = 0;
4483    return 1;
4484 }
4485
4486 static int
4487 _e_border_action_input_win_new(E_Border *bd)
4488 {
4489    if (!action_input_win)
4490      {
4491         Ecore_X_Window parent = bd->zone->container->win;
4492         action_input_win = ecore_x_window_input_new(parent, 0, 0, 1, 1);
4493         if (!action_input_win)
4494           return 0;
4495      }
4496
4497    ecore_x_window_show(action_input_win);
4498    if (e_grabinput_get(action_input_win, 0, action_input_win))
4499      return 1;
4500
4501    _e_border_action_input_win_del();
4502    return 0;
4503 }
4504
4505 static void
4506 _e_border_action_finish(void)
4507 {
4508    _e_border_action_input_win_del();
4509
4510    if (action_timer)
4511      {
4512         ecore_timer_del(action_timer);
4513         action_timer = NULL;
4514      }
4515
4516    if (action_handler_key)
4517      {
4518         ecore_event_handler_del(action_handler_key);
4519         action_handler_key = NULL;
4520      }
4521
4522    if (action_handler_mouse)
4523      {
4524         ecore_event_handler_del(action_handler_mouse);
4525         action_handler_mouse = NULL;
4526      }
4527
4528    action_border = NULL;
4529 }
4530
4531 static void
4532 _e_border_action_init(E_Border *bd)
4533 {
4534    action_orig.x = bd->x;
4535    action_orig.y = bd->y;
4536    action_orig.width = bd->w;
4537    action_orig.height = bd->h;
4538
4539    action_border = bd;
4540 }
4541
4542 static void
4543 _e_border_action_restore_orig(E_Border *bd)
4544 {
4545    if (action_border != bd)
4546      return;
4547
4548    e_border_move_resize(bd, action_orig.x, action_orig.y, action_orig.width, action_orig.height);
4549 }
4550
4551 static int
4552 _e_border_key_down_modifier_apply(int modifier,
4553                                   int value)
4554 {
4555    if (modifier & ECORE_EVENT_MODIFIER_CTRL)
4556      return value * 2;
4557    else if (modifier & ECORE_EVENT_MODIFIER_ALT)
4558      {
4559         value /= 2;
4560         if (value)
4561           return value;
4562         else
4563           return 1;
4564      }
4565
4566    return value;
4567 }
4568
4569 static Eina_Bool
4570 _e_border_action_move_timeout(void *data __UNUSED__)
4571 {
4572    _e_border_move_end(action_border);
4573    _e_border_action_finish();
4574    return ECORE_CALLBACK_CANCEL;
4575 }
4576
4577 static void
4578 _e_border_action_move_timeout_add(void)
4579 {
4580    if (action_timer)
4581      ecore_timer_del(action_timer);
4582    action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_move_timeout, NULL);
4583 }
4584
4585 static Eina_Bool
4586 _e_border_move_key_down(void *data __UNUSED__,
4587                         int type   __UNUSED__,
4588                         void      *event)
4589 {
4590    Ecore_Event_Key *ev = event;
4591    int x, y;
4592
4593    if (ev->event_window != action_input_win)
4594      return ECORE_CALLBACK_PASS_ON;
4595    if (!action_border)
4596      {
4597         fputs("ERROR: no action_border!\n", stderr);
4598         goto stop;
4599      }
4600
4601    x = action_border->x;
4602    y = action_border->y;
4603
4604    if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
4605      y -= _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dy);
4606    else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
4607      y += _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dy);
4608    else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
4609      x -= _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dx);
4610    else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
4611      x += _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dx);
4612    else if (strcmp(ev->key, "Return") == 0)
4613      goto stop;
4614    else if (strcmp(ev->key, "Escape") == 0)
4615      {
4616         _e_border_action_restore_orig(action_border);
4617         goto stop;
4618      }
4619    else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
4620             (strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
4621      goto stop;
4622
4623    e_border_move(action_border, x, y);
4624    _e_border_action_move_timeout_add();
4625
4626    return ECORE_CALLBACK_PASS_ON;
4627
4628 stop:
4629    _e_border_move_end(action_border);
4630    _e_border_action_finish();
4631    return ECORE_CALLBACK_DONE;
4632 }
4633
4634 static Eina_Bool
4635 _e_border_move_mouse_down(void *data __UNUSED__,
4636                           int type   __UNUSED__,
4637                           void      *event)
4638 {
4639    Ecore_Event_Mouse_Button *ev = event;
4640
4641    if (ev->event_window != action_input_win)
4642      return ECORE_CALLBACK_PASS_ON;
4643
4644    if (!action_border)
4645      fputs("ERROR: no action_border!\n", stderr);
4646
4647    _e_border_move_end(action_border);
4648    _e_border_action_finish();
4649    return ECORE_CALLBACK_DONE;
4650 }
4651
4652 EAPI void
4653 e_border_act_move_keyboard(E_Border *bd)
4654 {
4655    if (!bd)
4656      return;
4657
4658    if (!_e_border_move_begin(bd))
4659      return;
4660
4661    if (!_e_border_action_input_win_new(bd))
4662      {
4663         _e_border_move_end(bd);
4664         return;
4665      }
4666
4667    _e_border_action_init(bd);
4668    _e_border_action_move_timeout_add();
4669    _e_border_move_update(bd);
4670
4671    if (action_handler_key)
4672      ecore_event_handler_del(action_handler_key);
4673    action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_move_key_down, NULL);
4674
4675    if (action_handler_mouse)
4676      ecore_event_handler_del(action_handler_mouse);
4677    action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_move_mouse_down, NULL);
4678 }
4679
4680 static Eina_Bool
4681 _e_border_action_resize_timeout(void *data __UNUSED__)
4682 {
4683    _e_border_resize_end(action_border);
4684    _e_border_action_finish();
4685    return ECORE_CALLBACK_CANCEL;
4686 }
4687
4688 static void
4689 _e_border_action_resize_timeout_add(void)
4690 {
4691    if (action_timer)
4692      ecore_timer_del(action_timer);
4693    action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_resize_timeout, NULL);
4694 }
4695
4696 static Eina_Bool
4697 _e_border_resize_key_down(void *data __UNUSED__,
4698                           int type   __UNUSED__,
4699                           void      *event)
4700 {
4701    Ecore_Event_Key *ev = event;
4702    int w, h, dx, dy;
4703
4704    if (ev->event_window != action_input_win)
4705      return ECORE_CALLBACK_PASS_ON;
4706    if (!action_border)
4707      {
4708         fputs("ERROR: no action_border!\n", stderr);
4709         goto stop;
4710      }
4711
4712    w = action_border->w;
4713    h = action_border->h;
4714
4715    dx = e_config->border_keyboard.resize.dx;
4716    if (dx < action_border->client.icccm.step_w)
4717      dx = action_border->client.icccm.step_w;
4718    dx = _e_border_key_down_modifier_apply(ev->modifiers, dx);
4719    if (dx < action_border->client.icccm.step_w)
4720      dx = action_border->client.icccm.step_w;
4721
4722    dy = e_config->border_keyboard.resize.dy;
4723    if (dy < action_border->client.icccm.step_h)
4724      dy = action_border->client.icccm.step_h;
4725    dy = _e_border_key_down_modifier_apply(ev->modifiers, dy);
4726    if (dy < action_border->client.icccm.step_h)
4727      dy = action_border->client.icccm.step_h;
4728
4729    if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
4730      h -= dy;
4731    else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
4732      h += dy;
4733    else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
4734      w -= dx;
4735    else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
4736      w += dx;
4737    else if (strcmp(ev->key, "Return") == 0)
4738      goto stop;
4739    else if (strcmp(ev->key, "Escape") == 0)
4740      {
4741         _e_border_action_restore_orig(action_border);
4742         goto stop;
4743      }
4744    else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
4745             (strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
4746      goto stop;
4747
4748    e_border_resize_limit(action_border, &w, &h);
4749    e_border_resize(action_border, w, h);
4750    _e_border_action_resize_timeout_add();
4751
4752    return ECORE_CALLBACK_PASS_ON;
4753
4754 stop:
4755    _e_border_resize_end(action_border);
4756    _e_border_action_finish();
4757    return ECORE_CALLBACK_DONE;
4758 }
4759
4760 static Eina_Bool
4761 _e_border_resize_mouse_down(void *data __UNUSED__,
4762                             int type   __UNUSED__,
4763                             void      *event)
4764 {
4765    Ecore_Event_Mouse_Button *ev = event;
4766
4767    if (ev->event_window != action_input_win)
4768      return ECORE_CALLBACK_PASS_ON;
4769
4770    if (!action_border)
4771      fputs("ERROR: no action_border!\n", stderr);
4772
4773    _e_border_resize_end(action_border);
4774    _e_border_action_finish();
4775    return ECORE_CALLBACK_DONE;
4776 }
4777
4778 EAPI void
4779 e_border_act_resize_keyboard(E_Border *bd)
4780 {
4781    if (!bd)
4782      return;
4783
4784    if (!_e_border_resize_begin(bd))
4785      return;
4786
4787    if (!_e_border_action_input_win_new(bd))
4788      {
4789         _e_border_resize_end(bd);
4790         return;
4791      }
4792
4793    _e_border_action_init(bd);
4794    _e_border_action_resize_timeout_add();
4795    _e_border_resize_update(bd);
4796
4797    if (action_handler_key)
4798      ecore_event_handler_del(action_handler_key);
4799    action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_resize_key_down, NULL);
4800
4801    if (action_handler_mouse)
4802      ecore_event_handler_del(action_handler_mouse);
4803    action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_resize_mouse_down, NULL);
4804 }
4805
4806 EAPI void
4807 e_border_act_move_begin(E_Border                 *bd,
4808                         Ecore_Event_Mouse_Button *ev)
4809 {
4810    E_OBJECT_CHECK(bd);
4811    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4812    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
4813    if (!_e_border_move_begin(bd))
4814      return;
4815
4816    e_zone_edge_disable();
4817    bd->moving = 1;
4818    _e_border_pointer_move_begin(bd);
4819    if (ev)
4820      {
4821         char source[256];
4822
4823         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->buttons);
4824         _e_border_moveinfo_gather(bd, source);
4825      }
4826 }
4827
4828 EAPI void
4829 e_border_act_move_end(E_Border                    *bd,
4830                       Ecore_Event_Mouse_Button *ev __UNUSED__)
4831 {
4832    E_OBJECT_CHECK(bd);
4833    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4834    if (!bd->moving) return;
4835    bd->moving = 0;
4836    _e_border_pointer_move_end(bd);
4837    e_zone_edge_enable();
4838    _e_border_move_end(bd);
4839    e_zone_flip_coords_handle(bd->zone, -1, -1);
4840 }
4841
4842 EAPI void
4843 e_border_act_resize_begin(E_Border                 *bd,
4844                           Ecore_Event_Mouse_Button *ev)
4845 {
4846    E_OBJECT_CHECK(bd);
4847    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4848    if (bd->lock_user_size) return;
4849    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
4850    if (!_e_border_resize_begin(bd))
4851      return;
4852    if (bd->mouse.current.mx < (bd->x + bd->w / 2))
4853      {
4854         if (bd->mouse.current.my < (bd->y + bd->h / 2))
4855           {
4856              bd->resize_mode = RESIZE_TL;
4857              GRAV_SET(bd, ECORE_X_GRAVITY_SE);
4858           }
4859         else
4860           {
4861              bd->resize_mode = RESIZE_BL;
4862              GRAV_SET(bd, ECORE_X_GRAVITY_NE);
4863           }
4864      }
4865    else
4866      {
4867         if (bd->mouse.current.my < (bd->y + bd->h / 2))
4868           {
4869              bd->resize_mode = RESIZE_TR;
4870              GRAV_SET(bd, ECORE_X_GRAVITY_SW);
4871           }
4872         else
4873           {
4874              bd->resize_mode = RESIZE_BR;
4875              GRAV_SET(bd, ECORE_X_GRAVITY_NW);
4876           }
4877      }
4878    _e_border_pointer_resize_begin(bd);
4879    if (ev)
4880      {
4881         char source[256];
4882
4883         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->buttons);
4884         _e_border_moveinfo_gather(bd, source);
4885      }
4886 }
4887
4888 EAPI void
4889 e_border_act_resize_end(E_Border                    *bd,
4890                         Ecore_Event_Mouse_Button *ev __UNUSED__)
4891 {
4892    E_OBJECT_CHECK(bd);
4893    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4894    if (bd->resize_mode != RESIZE_NONE)
4895      {
4896         _e_border_pointer_resize_end(bd);
4897         bd->resize_mode = RESIZE_NONE;
4898         _e_border_resize_end(bd);
4899         bd->changes.reset_gravity = 1;
4900         bd->changed = 1;
4901      }
4902 }
4903
4904 EAPI void
4905 e_border_act_menu_begin(E_Border                 *bd,
4906                         Ecore_Event_Mouse_Button *ev,
4907                         int                       key)
4908 {
4909    E_OBJECT_CHECK(bd);
4910    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4911    if (ev)
4912      {
4913         e_int_border_menu_show(bd,
4914                                bd->x + bd->fx.x + ev->x - bd->zone->container->x,
4915                                bd->y + bd->fx.y + ev->y - bd->zone->container->y, key,
4916                                ev->timestamp);
4917      }
4918    else
4919      {
4920         int x, y;
4921
4922         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
4923         e_int_border_menu_show(bd, x, y, key, 0);
4924      }
4925 }
4926
4927 EAPI void
4928 e_border_act_close_begin(E_Border *bd)
4929 {
4930    E_OBJECT_CHECK(bd);
4931    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4932    if (bd->lock_close) return;
4933    if (bd->client.icccm.delete_request)
4934      {
4935         bd->delete_requested = 1;
4936         ecore_x_window_delete_request_send(bd->client.win);
4937         if (bd->client.netwm.ping)
4938           e_border_ping(bd);
4939      }
4940    else if (e_config->kill_if_close_not_possible)
4941      {
4942         e_border_act_kill_begin(bd);
4943      }
4944 }
4945
4946 EAPI void
4947 e_border_act_kill_begin(E_Border *bd)
4948 {
4949    E_OBJECT_CHECK(bd);
4950    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4951    if (bd->internal) return;
4952    if (bd->lock_close) return;
4953    if ((bd->client.netwm.pid > 1) && (e_config->kill_process))
4954      {
4955         kill(bd->client.netwm.pid, SIGINT);
4956         bd->kill_timer = ecore_timer_add(e_config->kill_timer_wait,
4957                                          _e_border_cb_kill_timer, bd);
4958      }
4959    else
4960      {
4961         if (!bd->internal) ecore_x_kill(bd->client.win);
4962      }
4963 }
4964
4965 EAPI Evas_Object *
4966 e_border_icon_add(E_Border *bd,
4967                   Evas     *evas)
4968 {
4969    Evas_Object *o;
4970
4971    E_OBJECT_CHECK_RETURN(bd, NULL);
4972    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, NULL);
4973
4974    o = NULL;
4975    if (bd->internal)
4976      {
4977         if (!bd->internal_icon)
4978           {
4979              o = e_icon_add(evas);
4980              e_util_icon_theme_set(o, "enlightenment");
4981           }
4982         else
4983           {
4984              if (!bd->internal_icon_key)
4985                {
4986                   char *ext;
4987
4988                   ext = strrchr(bd->internal_icon, '.');
4989                   if ((ext) && ((!strcmp(ext, ".edj"))))
4990                     {
4991                        o = edje_object_add(evas);
4992                        if (!edje_object_file_set(o, bd->internal_icon, "icon"))
4993                          e_util_icon_theme_set(o, "enlightenment");
4994                     }
4995                   else if (ext)
4996                     {
4997                        o = e_icon_add(evas);
4998                        e_icon_file_set(o, bd->internal_icon);
4999                     }
5000                   else
5001                     {
5002                        o = e_icon_add(evas);
5003                        if (!e_util_icon_theme_set(o, bd->internal_icon))
5004                          e_util_icon_theme_set(o, "enlightenment");
5005                     }
5006                }
5007              else
5008                {
5009                   o = edje_object_add(evas);
5010                   edje_object_file_set(o, bd->internal_icon,
5011                                        bd->internal_icon_key);
5012                }
5013           }
5014         return o;
5015      }
5016    if ((e_config->use_app_icon) && (bd->icon_preference != E_ICON_PREF_USER))
5017      {
5018         if (bd->client.netwm.icons)
5019           {
5020              o = e_icon_add(evas);
5021              e_icon_data_set(o, bd->client.netwm.icons[0].data,
5022                              bd->client.netwm.icons[0].width,
5023                              bd->client.netwm.icons[0].height);
5024              e_icon_alpha_set(o, 1);
5025              return o;
5026           }
5027      }
5028    if (!o)
5029      {
5030         if ((bd->desktop) && (bd->icon_preference != E_ICON_PREF_NETWM))
5031           {
5032              o = e_icon_add(evas);
5033              if (o)
5034                {
5035                   e_icon_fdo_icon_set(o, bd->desktop->icon);
5036                   return o;
5037                }
5038           }
5039         else if (bd->client.netwm.icons)
5040           {
5041              o = e_icon_add(evas);
5042              e_icon_data_set(o, bd->client.netwm.icons[0].data,
5043                              bd->client.netwm.icons[0].width,
5044                              bd->client.netwm.icons[0].height);
5045              e_icon_alpha_set(o, 1);
5046              return o;
5047           }
5048      }
5049
5050    o = e_icon_add(evas);
5051    e_util_icon_theme_set(o, "unknown");
5052    return o;
5053 }
5054
5055 EAPI void
5056 e_border_button_bindings_ungrab_all(void)
5057 {
5058    Eina_List *l;
5059    E_Border *bd;
5060
5061    EINA_LIST_FOREACH(borders, l, bd)
5062      {
5063         e_focus_setdown(bd);
5064         e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5065         e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5066      }
5067 }
5068
5069 EAPI void
5070 e_border_button_bindings_grab_all(void)
5071 {
5072    Eina_List *l;
5073    E_Border *bd;
5074
5075    EINA_LIST_FOREACH(borders, l, bd)
5076      {
5077         e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
5078         e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
5079         e_focus_setup(bd);
5080      }
5081 }
5082
5083 EAPI Eina_List *
5084 e_border_focus_stack_get(void)
5085 {
5086    return focus_stack;
5087 }
5088
5089 EAPI Eina_List *
5090 e_border_raise_stack_get(void)
5091 {
5092    return raise_stack;
5093 }
5094
5095 EAPI Eina_List *
5096 e_border_lost_windows_get(E_Zone *zone)
5097 {
5098    Eina_List *list = NULL, *l;
5099    E_Border *bd;
5100    int loss_overlap = 5;
5101
5102    E_OBJECT_CHECK_RETURN(zone, NULL);
5103    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
5104    EINA_LIST_FOREACH(borders, l, bd)
5105      {
5106         if (!bd->zone)
5107           continue;
5108
5109         if ((bd->zone != zone) ||
5110             (bd->zone->container != zone->container))
5111           continue;
5112
5113         if (!E_INTERSECTS(bd->zone->x + loss_overlap,
5114                           bd->zone->y + loss_overlap,
5115                           bd->zone->w - (2 * loss_overlap),
5116                           bd->zone->h - (2 * loss_overlap),
5117                           bd->x, bd->y, bd->w, bd->h))
5118           {
5119              list = eina_list_append(list, bd);
5120           }
5121         else if ((!E_CONTAINS(bd->zone->x, bd->zone->y,
5122                               bd->zone->w, bd->zone->h,
5123                               bd->x, bd->y, bd->w, bd->h)) &&
5124                  (bd->shaped))
5125           {
5126              Ecore_X_Rectangle *rect;
5127              int i, num;
5128
5129              rect = ecore_x_window_shape_rectangles_get(bd->win, &num);
5130              if (rect)
5131                {
5132                   int ok;
5133
5134                   ok = 0;
5135                   for (i = 0; i < num; i++)
5136                     {
5137                        if (E_INTERSECTS(bd->zone->x + loss_overlap,
5138                                         bd->zone->y + loss_overlap,
5139                                         bd->zone->w - (2 * loss_overlap),
5140                                         bd->zone->h - (2 * loss_overlap),
5141                                         rect[i].x, rect[i].y,
5142                                         (int)rect[i].width, (int)rect[i].height))
5143                          {
5144                             ok = 1;
5145                             break;
5146                          }
5147                     }
5148                   free(rect);
5149                   if (!ok)
5150                     list = eina_list_append(list, bd);
5151                }
5152           }
5153      }
5154    return list;
5155 }
5156
5157 EAPI void
5158 e_border_ping(E_Border *bd)
5159 {
5160    E_OBJECT_CHECK(bd);
5161    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5162    if (!e_config->ping_clients) return;
5163    bd->ping_ok = 0;
5164    ecore_x_netwm_ping_send(bd->client.win);
5165    bd->ping = ecore_loop_time_get();
5166    if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
5167    bd->ping_poller = ecore_poller_add(ECORE_POLLER_CORE,
5168                                       e_config->ping_clients_interval,
5169                                       _e_border_cb_ping_poller, bd);
5170 }
5171
5172 EAPI void
5173 e_border_move_cancel(void)
5174 {
5175    if (bdmove)
5176      {
5177         if (bdmove->cur_mouse_action)
5178           {
5179              E_Border *bd;
5180
5181              bd = bdmove;
5182              e_object_ref(E_OBJECT(bd));
5183              if (bd->cur_mouse_action->func.end_mouse)
5184                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
5185              else if (bd->cur_mouse_action->func.end)
5186                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
5187              e_object_unref(E_OBJECT(bd->cur_mouse_action));
5188              bd->cur_mouse_action = NULL;
5189              e_object_unref(E_OBJECT(bd));
5190           }
5191         else
5192           _e_border_move_end(bdmove);
5193      }
5194 }
5195
5196 EAPI void
5197 e_border_resize_cancel(void)
5198 {
5199    if (bdresize)
5200      {
5201         if (bdresize->cur_mouse_action)
5202           {
5203              E_Border *bd;
5204
5205              bd = bdresize;
5206              e_object_ref(E_OBJECT(bd));
5207              if (bd->cur_mouse_action->func.end_mouse)
5208                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
5209              else if (bd->cur_mouse_action->func.end)
5210                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
5211              e_object_unref(E_OBJECT(bd->cur_mouse_action));
5212              bd->cur_mouse_action = NULL;
5213              e_object_unref(E_OBJECT(bd));
5214           }
5215         else
5216           {
5217              bdresize->resize_mode = RESIZE_NONE;
5218              _e_border_resize_end(bdresize);
5219           }
5220      }
5221 }
5222
5223 EAPI void
5224 e_border_frame_recalc(E_Border *bd)
5225 {
5226    if (!bd->bg_object) return;
5227
5228    bd->w -= (bd->client_inset.l + bd->client_inset.r);
5229    bd->h -= (bd->client_inset.t + bd->client_inset.b);
5230
5231    _e_border_client_inset_calc(bd);
5232
5233    bd->w += (bd->client_inset.l + bd->client_inset.r);
5234    bd->h += (bd->client_inset.t + bd->client_inset.b);
5235
5236    bd->changed = 1;
5237    bd->changes.size = 1;
5238    if ((bd->shaped) || (bd->client.shaped))
5239      {
5240         bd->need_shape_merge = 1;
5241         bd->need_shape_export = 1;
5242      }
5243    if (bd->shaped_input)
5244      {
5245         bd->need_shape_merge = 1;
5246      }
5247    _e_border_client_move_resize_send(bd);
5248 }
5249
5250 EAPI Eina_List *
5251 e_border_immortal_windows_get(void)
5252 {
5253    Eina_List *list = NULL, *l;
5254    E_Border *bd;
5255
5256    EINA_LIST_FOREACH(borders, l, bd)
5257      {
5258         if (bd->lock_life)
5259           list = eina_list_append(list, bd);
5260      }
5261    return list;
5262 }
5263
5264 EAPI const char *
5265 e_border_name_get(const E_Border *bd)
5266 {
5267    E_OBJECT_CHECK_RETURN(bd, "");
5268    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, "");
5269    if (bd->client.netwm.name)
5270      return bd->client.netwm.name;
5271    else if (bd->client.icccm.title)
5272      return bd->client.icccm.title;
5273    return "";
5274 }
5275
5276 EAPI void
5277 e_border_signal_move_begin(E_Border       *bd,
5278                            const char     *sig,
5279                            const char *src __UNUSED__)
5280 {
5281    E_OBJECT_CHECK(bd);
5282    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5283
5284    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
5285    if (!_e_border_move_begin(bd)) return;
5286    bd->moving = 1;
5287    _e_border_pointer_move_begin(bd);
5288    e_zone_edge_disable();
5289    _e_border_moveinfo_gather(bd, sig);
5290    if (bd->cur_mouse_action)
5291      {
5292         if ((!bd->cur_mouse_action->func.end_mouse) &&
5293             (!bd->cur_mouse_action->func.end))
5294           bd->cur_mouse_action = NULL;
5295         else
5296           e_object_unref(E_OBJECT(bd->cur_mouse_action));
5297      }
5298    bd->cur_mouse_action = e_action_find("window_move");
5299    if (bd->cur_mouse_action)
5300      e_object_ref(E_OBJECT(bd->cur_mouse_action));
5301 }
5302
5303 EAPI void
5304 e_border_signal_move_end(E_Border       *bd,
5305                          const char *sig __UNUSED__,
5306                          const char *src __UNUSED__)
5307 {
5308    E_OBJECT_CHECK(bd);
5309    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5310    if (!bd->moving) return;
5311    bd->moving = 0;
5312    _e_border_pointer_move_end(bd);
5313    e_zone_edge_enable();
5314    _e_border_move_end(bd);
5315    e_zone_flip_coords_handle(bd->zone, -1, -1);
5316 }
5317
5318 EAPI int
5319 e_border_resizing_get(E_Border *bd)
5320 {
5321    E_OBJECT_CHECK_RETURN(bd, 0);
5322    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, 0);
5323    if (bd->resize_mode == RESIZE_NONE) return 0;
5324    return 1;
5325 }
5326
5327 EAPI void
5328 e_border_signal_resize_begin(E_Border       *bd,
5329                              const char     *dir,
5330                              const char     *sig,
5331                              const char *src __UNUSED__)
5332 {
5333    Ecore_X_Gravity grav = ECORE_X_GRAVITY_NW;
5334    int resize_mode = RESIZE_BR;
5335
5336    E_OBJECT_CHECK(bd);
5337    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5338
5339    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
5340    if (!_e_border_resize_begin(bd))
5341      return;
5342    if (!strcmp(dir, "tl"))
5343      {
5344         resize_mode = RESIZE_TL;
5345         grav = ECORE_X_GRAVITY_SE;
5346      }
5347    else if (!strcmp(dir, "t"))
5348      {
5349         resize_mode = RESIZE_T;
5350         grav = ECORE_X_GRAVITY_S;
5351      }
5352    else if (!strcmp(dir, "tr"))
5353      {
5354         resize_mode = RESIZE_TR;
5355         grav = ECORE_X_GRAVITY_SW;
5356      }
5357    else if (!strcmp(dir, "r"))
5358      {
5359         resize_mode = RESIZE_R;
5360         grav = ECORE_X_GRAVITY_W;
5361      }
5362    else if (!strcmp(dir, "br"))
5363      {
5364         resize_mode = RESIZE_BR;
5365         grav = ECORE_X_GRAVITY_NW;
5366      }
5367    else if (!strcmp(dir, "b"))
5368      {
5369         resize_mode = RESIZE_B;
5370         grav = ECORE_X_GRAVITY_N;
5371      }
5372    else if (!strcmp(dir, "bl"))
5373      {
5374         resize_mode = RESIZE_BL;
5375         grav = ECORE_X_GRAVITY_NE;
5376      }
5377    else if (!strcmp(dir, "l"))
5378      {
5379         resize_mode = RESIZE_L;
5380         grav = ECORE_X_GRAVITY_E;
5381      }
5382    bd->resize_mode = resize_mode;
5383    _e_border_pointer_resize_begin(bd);
5384    _e_border_moveinfo_gather(bd, sig);
5385    GRAV_SET(bd, grav);
5386    if (bd->cur_mouse_action)
5387      {
5388         if ((!bd->cur_mouse_action->func.end_mouse) &&
5389             (!bd->cur_mouse_action->func.end))
5390           bd->cur_mouse_action = NULL;
5391         else
5392           e_object_unref(E_OBJECT(bd->cur_mouse_action));
5393      }
5394    bd->cur_mouse_action = e_action_find("window_resize");
5395    if (bd->cur_mouse_action)
5396      e_object_ref(E_OBJECT(bd->cur_mouse_action));
5397 }
5398
5399 EAPI void
5400 e_border_signal_resize_end(E_Border       *bd,
5401                            const char *dir __UNUSED__,
5402                            const char *sig __UNUSED__,
5403                            const char *src __UNUSED__)
5404 {
5405    E_OBJECT_CHECK(bd);
5406    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5407    if (bd->resize_mode == RESIZE_NONE) return;
5408    _e_border_resize_handle(bd);
5409    _e_border_pointer_resize_end(bd);
5410    bd->resize_mode = RESIZE_NONE;
5411    _e_border_resize_end(bd);
5412    bd->changes.reset_gravity = 1;
5413    bd->changed = 1;
5414 }
5415
5416 EAPI void
5417 e_border_resize_limit(E_Border *bd,
5418                       int      *w,
5419                       int      *h)
5420 {
5421    double a;
5422
5423    E_OBJECT_CHECK(bd);
5424    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5425    *w -= bd->client_inset.l + bd->client_inset.r;
5426    *h -= bd->client_inset.t + bd->client_inset.b;
5427    if (*h < 1) *h = 1;
5428    if (*w < 1) *w = 1;
5429    if ((bd->client.icccm.base_w >= 0) &&
5430        (bd->client.icccm.base_h >= 0))
5431      {
5432         int tw, th;
5433
5434         tw = *w - bd->client.icccm.base_w;
5435         th = *h - bd->client.icccm.base_h;
5436         if (tw < 1) tw = 1;
5437         if (th < 1) th = 1;
5438         a = (double)(tw) / (double)(th);
5439         if ((bd->client.icccm.min_aspect != 0.0) &&
5440             (a < bd->client.icccm.min_aspect))
5441           {
5442              th = tw / bd->client.icccm.max_aspect;
5443              *h = th + bd->client.icccm.base_h;
5444           }
5445         else if ((bd->client.icccm.max_aspect != 0.0) &&
5446                  (a > bd->client.icccm.max_aspect))
5447           {
5448              tw = th * bd->client.icccm.max_aspect;
5449              *w = tw + bd->client.icccm.base_w;
5450           }
5451      }
5452    else
5453      {
5454         a = (double)*w / (double)*h;
5455         if ((bd->client.icccm.min_aspect != 0.0) &&
5456             (a < bd->client.icccm.min_aspect))
5457           *h = *w / bd->client.icccm.min_aspect;
5458         else if ((bd->client.icccm.max_aspect != 0.0) &&
5459                  (a > bd->client.icccm.max_aspect))
5460           *w = *h * bd->client.icccm.max_aspect;
5461      }
5462    if (bd->client.icccm.step_w > 0)
5463      {
5464         if (bd->client.icccm.base_w >= 0)
5465           *w = bd->client.icccm.base_w +
5466             (((*w - bd->client.icccm.base_w) / bd->client.icccm.step_w) *
5467              bd->client.icccm.step_w);
5468         else
5469           *w = bd->client.icccm.min_w +
5470             (((*w - bd->client.icccm.min_w) / bd->client.icccm.step_w) *
5471              bd->client.icccm.step_w);
5472      }
5473    if (bd->client.icccm.step_h > 0)
5474      {
5475         if (bd->client.icccm.base_h >= 0)
5476           *h = bd->client.icccm.base_h +
5477             (((*h - bd->client.icccm.base_h) / bd->client.icccm.step_h) *
5478              bd->client.icccm.step_h);
5479         else
5480           *h = bd->client.icccm.min_h +
5481             (((*h - bd->client.icccm.min_h) / bd->client.icccm.step_h) *
5482              bd->client.icccm.step_h);
5483      }
5484
5485    if (*h < 1) *h = 1;
5486    if (*w < 1) *w = 1;
5487
5488    if      (*w > bd->client.icccm.max_w) *w = bd->client.icccm.max_w;
5489    else if (*w < bd->client.icccm.min_w)
5490      *w = bd->client.icccm.min_w;
5491    if      (*h > bd->client.icccm.max_h) *h = bd->client.icccm.max_h;
5492    else if (*h < bd->client.icccm.min_h)
5493      *h = bd->client.icccm.min_h;
5494
5495    *w += bd->client_inset.l + bd->client_inset.r;
5496    *h += bd->client_inset.t + bd->client_inset.b;
5497 }
5498
5499 /* local subsystem functions */
5500 static void
5501 _e_border_free(E_Border *bd)
5502 {
5503 #ifdef _F_USE_DESK_WINDOW_PROFILE_
5504    const char *str;
5505 #endif
5506    if (bd->client.e.state.video_parent && bd->client.e.state.video_parent_border)
5507      {
5508         bd->client.e.state.video_parent_border->client.e.state.video_child =
5509           eina_list_remove
5510           (bd->client.e.state.video_parent_border->client.e.state.video_child,
5511               bd);
5512      }
5513    if (bd->client.e.state.video_child)
5514      {
5515         E_Border *tmp;
5516
5517         EINA_LIST_FREE(bd->client.e.state.video_child, tmp)
5518           {
5519              tmp->client.e.state.video_parent_border = NULL;
5520           }
5521      }
5522    if (bd->desktop)
5523      {
5524         efreet_desktop_free(bd->desktop);
5525         bd->desktop = NULL;
5526      }
5527    if (bd->post_job)
5528      {
5529         ecore_idle_enterer_del(bd->post_job);
5530         bd->post_job = NULL;
5531      }
5532    if (bd->pointer)
5533      {
5534         e_object_del(E_OBJECT(bd->pointer));
5535         bd->pointer = NULL;
5536      }
5537    if (bdresize == bd)
5538      _e_border_resize_end(bd);
5539    if (bdmove == bd)
5540      _e_border_move_end(bd);
5541    /* TODO: Other states to end before dying? */
5542
5543    if (bd->cur_mouse_action)
5544      {
5545         e_object_unref(E_OBJECT(bd->cur_mouse_action));
5546         bd->cur_mouse_action = NULL;
5547      }
5548
5549    E_FREE(bd->shape_rects);
5550    bd->shape_rects_num = 0;
5551 /*
5552    if (bd->dangling_ref_check)
5553      {
5554         ecore_timer_del(bd->dangling_ref_check);
5555         bd->dangling_ref_check = NULL;
5556      }
5557  */
5558    if (bd->kill_timer)
5559      {
5560         ecore_timer_del(bd->kill_timer);
5561         bd->kill_timer = NULL;
5562      }
5563    if (bd->ping_poller)
5564      {
5565         ecore_poller_del(bd->ping_poller);
5566         bd->ping_poller = NULL;
5567      }
5568    E_FREE_LIST(bd->pending_move_resize, free);
5569
5570    if (bd->shade.anim) ecore_animator_del(bd->shade.anim);
5571    if (bd->border_menu) e_menu_deactivate(bd->border_menu);
5572
5573    if (bd->border_locks_dialog)
5574      {
5575         e_object_del(E_OBJECT(bd->border_locks_dialog));
5576         bd->border_locks_dialog = NULL;
5577      }
5578    if (bd->border_remember_dialog)
5579      {
5580         e_object_del(E_OBJECT(bd->border_remember_dialog));
5581         bd->border_remember_dialog = NULL;
5582      }
5583    if (bd->border_border_dialog)
5584      {
5585         e_object_del(E_OBJECT(bd->border_border_dialog));
5586         bd->border_border_dialog = NULL;
5587      }
5588    if (bd->border_prop_dialog)
5589      {
5590         e_object_del(E_OBJECT(bd->border_prop_dialog));
5591         bd->border_prop_dialog = NULL;
5592      }
5593
5594    e_int_border_menu_del(bd);
5595
5596    if (focusing == bd)
5597      focusing = NULL;
5598
5599    focus_next = eina_list_remove(focus_next, bd);
5600    
5601    if ((focused == bd) ||
5602        (e_grabinput_last_focus_win_get() == bd->client.win))
5603      {
5604         if ((!focus_next) && (!focusing))
5605           {
5606              e_grabinput_focus(bd->zone->container->bg_win,
5607                                E_FOCUS_METHOD_PASSIVE);
5608              e_hints_active_window_set(bd->zone->container->manager, NULL);
5609           }
5610
5611         focused = NULL;
5612      }
5613    E_FREE_LIST(bd->handlers, ecore_event_handler_del);
5614    if (bd->remember)
5615      {
5616         E_Remember *rem;
5617
5618         rem = bd->remember;
5619         bd->remember = NULL;
5620         e_remember_unuse(rem);
5621      }
5622    if (!bd->already_unparented)
5623      {
5624         ecore_x_window_reparent(bd->client.win, bd->zone->container->manager->root,
5625                                 bd->x + bd->client_inset.l, bd->y + bd->client_inset.t);
5626         ecore_x_window_save_set_del(bd->client.win);
5627         bd->already_unparented = 1;
5628      }
5629    if (bd->group) eina_list_free(bd->group);
5630    if (bd->transients) eina_list_free(bd->transients);
5631    if (bd->stick_desks) eina_list_free(bd->stick_desks);
5632    if (bd->client.netwm.icons)
5633      {
5634         int i;
5635         for (i = 0; i < bd->client.netwm.num_icons; i++)
5636           free(bd->client.netwm.icons[i].data);
5637         free(bd->client.netwm.icons);
5638      }
5639    if (bd->client.netwm.extra_types)
5640      free(bd->client.netwm.extra_types);
5641    if (bd->client.border.name)
5642      eina_stringshare_del(bd->client.border.name);
5643    if (bd->bordername)
5644      eina_stringshare_del(bd->bordername);
5645    if (bd->client.icccm.name)
5646      eina_stringshare_del(bd->client.icccm.name);
5647    if (bd->client.icccm.class)
5648      {
5649         if (!strcmp(bd->client.icccm.class, "Vmplayer"))
5650           e_bindings_mapping_change_enable(EINA_TRUE);
5651         eina_stringshare_del(bd->client.icccm.class);
5652      }
5653    if (bd->client.icccm.title)
5654      eina_stringshare_del(bd->client.icccm.title);
5655    if (bd->client.icccm.icon_name)
5656      eina_stringshare_del(bd->client.icccm.icon_name);
5657    if (bd->client.icccm.machine)
5658      eina_stringshare_del(bd->client.icccm.machine);
5659    if (bd->client.icccm.window_role)
5660      eina_stringshare_del(bd->client.icccm.window_role);
5661
5662    if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
5663      {
5664         int i;
5665
5666         for (i = 0; i < bd->client.icccm.command.argc; i++)
5667           free(bd->client.icccm.command.argv[i]);
5668         free(bd->client.icccm.command.argv);
5669      }
5670    if (bd->client.netwm.name)
5671      eina_stringshare_del(bd->client.netwm.name);
5672    if (bd->client.netwm.icon_name)
5673      eina_stringshare_del(bd->client.netwm.icon_name);
5674    e_object_del(E_OBJECT(bd->shape));
5675    if (bd->internal_icon) eina_stringshare_del(bd->internal_icon);
5676    if (bd->internal_icon_key) eina_stringshare_del(bd->internal_icon_key);
5677    if (bd->icon_object) evas_object_del(bd->icon_object);
5678 #ifdef _F_USE_DESK_WINDOW_PROFILE_
5679    EINA_LIST_FREE(bd->client.e.state.profiles, str)
5680      {
5681         if (str) eina_stringshare_del(str);
5682      }
5683    bd->client.e.state.profiles = NULL;
5684    if (bd->client.e.state.profile)
5685      eina_stringshare_del(bd->client.e.state.profile);
5686    bd->client.e.state.profile = NULL;
5687 #endif
5688 #ifdef _F_ZONE_WINDOW_ROTATION_
5689    if (e_config->wm_win_rotation)
5690      {
5691         bd->client.e.fetch.rot.app_set = 0;
5692         bd->client.e.state.rot.preferred_rot = -1;
5693
5694         if (bd->client.e.state.rot.available_rots)
5695           E_FREE(bd->client.e.state.rot.available_rots);
5696
5697         _e_border_rotation_list_remove(bd);
5698         if ((rot.vkbd) && (rot.vkbd == bd))
5699           {
5700              ELB(ELBT_BD, "UNSET VKBD", bd->client.win);
5701              rot.vkbd = NULL;
5702              if (rot.vkbd_ctrl_win)
5703                {
5704                   ELB(ELBT_BD, "SET KBD_OFF", 0);
5705                   ecore_x_e_virtual_keyboard_state_set
5706                     (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
5707                }
5708
5709              rot.vkbd_hide_prepare_done = EINA_FALSE;
5710              if (rot.vkbd_hide_prepare_timer)
5711                ecore_timer_del(rot.vkbd_hide_prepare_timer);
5712              rot.vkbd_hide_prepare_timer = NULL;
5713              if (rot.vkbd_hide_timer)
5714                ecore_timer_del(rot.vkbd_hide_timer);
5715              rot.vkbd_hide_timer = NULL;
5716
5717              rot.vkbd_show_prepare_done = EINA_FALSE;
5718              if (rot.vkbd_show_prepare_timer)
5719                ecore_timer_del(rot.vkbd_show_prepare_timer);
5720              rot.vkbd_show_prepare_timer = NULL;
5721              if (rot.vkbd_show_timer)
5722                ecore_timer_del(rot.vkbd_show_timer);
5723              rot.vkbd_show_timer = NULL;
5724           }
5725         else if ((rot.vkbd_prediction) &&
5726                  (rot.vkbd_prediction == bd))
5727           rot.vkbd_prediction = NULL;
5728      }
5729 #endif
5730 #ifdef _F_DEICONIFY_APPROVE_
5731    if (bd->client.e.state.deiconify_approve.pending_job)
5732      {
5733         ecore_job_del(bd->client.e.state.deiconify_approve.pending_job);
5734         bd->client.e.state.deiconify_approve.pending_job = NULL;
5735      }
5736 #endif
5737    evas_object_del(bd->bg_object);
5738    e_canvas_del(bd->bg_ecore_evas);
5739    ecore_evas_free(bd->bg_ecore_evas);
5740    ecore_x_window_free(bd->client.shell_win);
5741    e_focus_setdown(bd);
5742    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5743    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5744    ecore_x_window_free(bd->win);
5745
5746    eina_hash_del(borders_hash, e_util_winid_str_get(bd->client.win), bd);
5747    eina_hash_del(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
5748    eina_hash_del(borders_hash, e_util_winid_str_get(bd->win), bd);
5749    borders = eina_list_remove(borders, bd);
5750    focus_stack = eina_list_remove(focus_stack, bd);
5751    raise_stack = eina_list_remove(raise_stack, bd);
5752
5753    e_container_border_remove(bd);
5754    free(bd);
5755 }
5756
5757 /*
5758    static int
5759    _e_border_del_dangling_ref_check(void *data)
5760    {
5761    E_Border *bd;
5762
5763    bd = data;
5764    printf("---\n");
5765    printf("EEK EEK border still around 1 second after being deleted!\n");
5766    printf("%p, %i, \"%s\" [\"%s\" \"%s\"]\n",
5767           bd, e_object_ref_get(E_OBJECT(bd)), bd->client.icccm.title,
5768           bd->client.icccm.name, bd->client.icccm.class);
5769    //   e_object_breadcrumb_debug(E_OBJECT(bd));
5770    printf("---\n");
5771    return 1;
5772    }
5773  */
5774
5775 static void
5776 _e_border_del(E_Border *bd)
5777 {
5778    E_Event_Border_Remove *ev;
5779    E_Border *child;
5780
5781 #ifdef _F_BORDER_HOOK_PATCH_
5782    _e_border_hook_call(E_BORDER_HOOK_DEL_BORDER, bd);
5783 #endif
5784
5785    if (bd == focused)
5786      {
5787         focused = NULL;
5788      }
5789
5790    if (bd == focusing)
5791      focusing = NULL;
5792
5793    focus_next = eina_list_remove(focus_next, bd);
5794
5795    if (bd->fullscreen) bd->desk->fullscreen_borders--;
5796
5797    if ((drag_border) && (drag_border->data == bd))
5798      {
5799         e_object_del(E_OBJECT(drag_border));
5800         drag_border = NULL;
5801      }
5802    if (bd->border_menu) e_menu_deactivate(bd->border_menu);
5803
5804    if (bd->border_locks_dialog)
5805      {
5806         e_object_del(E_OBJECT(bd->border_locks_dialog));
5807         bd->border_locks_dialog = NULL;
5808      }
5809    if (bd->border_remember_dialog)
5810      {
5811         e_object_del(E_OBJECT(bd->border_remember_dialog));
5812         bd->border_remember_dialog = NULL;
5813      }
5814    if (bd->border_border_dialog)
5815      {
5816         e_object_del(E_OBJECT(bd->border_border_dialog));
5817         bd->border_border_dialog = NULL;
5818      }
5819    if (bd->border_prop_dialog)
5820      {
5821         e_object_del(E_OBJECT(bd->border_prop_dialog));
5822         bd->border_prop_dialog = NULL;
5823      }
5824
5825    e_int_border_menu_del(bd);
5826
5827    if (bd->raise_timer)
5828      {
5829         ecore_timer_del(bd->raise_timer);
5830         bd->raise_timer = NULL;
5831      }
5832    if (!bd->already_unparented)
5833      {
5834         ecore_x_window_reparent(bd->client.win,
5835                                 bd->zone->container->manager->root,
5836                                 bd->x + bd->client_inset.l,
5837                                 bd->y + bd->client_inset.t);
5838         ecore_x_window_save_set_del(bd->client.win);
5839         bd->already_unparented = 1;
5840 //      bd->client.win = 0;
5841      }
5842    bd->already_unparented = 1;
5843
5844    if ((!bd->new_client) && (!stopping))
5845      {
5846         ev = E_NEW(E_Event_Border_Remove, 1);
5847         ev->border = bd;
5848         e_object_ref(E_OBJECT(bd));
5849         // e_object_breadcrumb_add(E_OBJECT(bd), "border_remove_event");
5850         ecore_event_add(E_EVENT_BORDER_REMOVE, ev, _e_border_event_border_remove_free, NULL);
5851      }
5852
5853    if (bd->parent)
5854      {
5855         bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
5856         if (bd->parent->modal == bd)
5857           {
5858              ecore_x_event_mask_unset(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
5859              ecore_x_event_mask_set(bd->parent->client.win, bd->parent->saved.event_mask);
5860              bd->parent->lock_close = 0;
5861              bd->parent->saved.event_mask = 0;
5862              bd->parent->modal = NULL;
5863           }
5864         bd->parent = NULL;
5865      }
5866    EINA_LIST_FREE(bd->transients, child)
5867      {
5868         child->parent = NULL;
5869      }
5870
5871 #ifdef _F_DEICONIFY_APPROVE_
5872    bd->client.e.state.deiconify_approve.render_done = 0;
5873
5874    E_Border *ancestor_bd;
5875    ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
5876    if ((ancestor_bd) &&
5877        (!e_object_is_del(E_OBJECT(ancestor_bd))))
5878      {
5879         ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
5880         bd->client.e.state.deiconify_approve.ancestor = NULL;
5881
5882         if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
5883             (ancestor_bd->client.e.state.deiconify_approve.render_done))
5884           {
5885              if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
5886                {
5887                   ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
5888                   ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
5889                   e_border_uniconify(ancestor_bd);
5890                }
5891           }
5892      }
5893
5894    if (bd->client.e.state.deiconify_approve.wait_timer)
5895      {
5896         ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer);
5897         bd->client.e.state.deiconify_approve.wait_timer = NULL;
5898      }
5899
5900    if (bd->client.e.state.deiconify_approve.req_list)
5901      {
5902         EINA_LIST_FREE(bd->client.e.state.deiconify_approve.req_list, child)
5903           {
5904              child->client.e.state.deiconify_approve.render_done = 0;
5905              child->client.e.state.deiconify_approve.ancestor = NULL;
5906           }
5907      }
5908 #endif
5909
5910 #ifdef _F_ZONE_WINDOW_ROTATION_
5911    if (rot.list) _e_border_rotation_list_remove(bd);
5912    if (rot.async_list)
5913      {
5914         Eina_List *l;
5915         E_Border_Rotation_Info *info = NULL;
5916
5917         EINA_LIST_FOREACH(rot.async_list, l, info)
5918            if (info->bd == bd)
5919              {
5920                 rot.async_list = eina_list_remove(rot.async_list, info);
5921                 E_FREE(info);
5922              }
5923      }
5924 #endif
5925
5926    if (bd->leader)
5927      {
5928         bd->leader->group = eina_list_remove(bd->leader->group, bd);
5929         if (bd->leader->modal == bd)
5930           bd->leader->modal = NULL;
5931         bd->leader = NULL;
5932      }
5933    EINA_LIST_FREE(bd->group, child)
5934      {
5935         child->leader = NULL;
5936      }
5937 }
5938
5939 #ifdef PRINT_LOTS_OF_DEBUG
5940 static void
5941 _e_border_print(E_Border   *bd,
5942                 const char *func)
5943 {
5944    if (!bd) return;
5945
5946    DBG("*Window Info*"
5947           "\tPointer: %p\n"
5948           "\tName: %s\n"
5949           "\tTitle: %s\n"
5950           "\tBorderless: %s\n",
5951           bd, bd->client.icccm.name, bd->client.icccm.title,
5952           bd->borderless ? "TRUE" : "FALSE");
5953 }
5954
5955 #endif
5956
5957 static Eina_Bool
5958 _e_border_cb_window_show_request(void *data  __UNUSED__,
5959                                  int ev_type __UNUSED__,
5960                                  void       *ev)
5961 {
5962    E_Border *bd;
5963    E_Container *con;
5964    Ecore_X_Event_Window_Show_Request *e;
5965
5966    e = ev;
5967    bd = e_border_find_by_client_window(e->win);
5968    if (!bd) return ECORE_CALLBACK_PASS_ON;
5969
5970    if ((e_config->wm_win_rotation) &&
5971        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
5972        (bd == rot.vkbd) &&
5973        (rot.vkbd_hide_prepare_timer))
5974      {
5975         con = bd->zone->container;
5976         bd = e_border_new(con, e->win, 0, 0);
5977      }
5978
5979    if (bd->iconic)
5980      {
5981         if (!bd->lock_client_iconify)
5982           e_border_uniconify(bd);
5983      }
5984    else
5985      {
5986         /* FIXME: make border "urgent" for a bit - it wants attention */
5987 /*      e_border_show(bd); */
5988           if (!bd->lock_client_stacking)
5989             e_border_raise(bd);
5990      }
5991    return ECORE_CALLBACK_PASS_ON;
5992 }
5993
5994 static Eina_Bool
5995 _e_border_cb_window_destroy(void *data  __UNUSED__,
5996                             int ev_type __UNUSED__,
5997                             void       *ev)
5998 {
5999    E_Border *bd;
6000    Ecore_X_Event_Window_Destroy *e;
6001
6002    e = ev;
6003    bd = e_border_find_by_client_window(e->win);
6004    if (!bd) return ECORE_CALLBACK_PASS_ON;
6005    ELB(ELBT_BD, "X_WIN_DEL", bd->client.win);
6006 #ifdef _F_ZONE_WINDOW_ROTATION_
6007    if (e_config->wm_win_rotation)
6008      {
6009         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
6010           {
6011              ELB(ELBT_BD, "X_DEL_NOTIFY", bd->client.win);
6012              if (!rot.vkbd_hide_prepare_timer)
6013                {
6014                   ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
6015                   e_border_hide(bd, 0);
6016                   if (!rot.vkbd_hide_prepare_timer)
6017                     {
6018                        ELB(ELBT_BD, "DEL VKBD", bd->client.win);
6019                        e_object_del(E_OBJECT(bd));
6020                     }
6021                }
6022              return ECORE_CALLBACK_PASS_ON;
6023           }
6024      }
6025 #endif
6026    e_border_hide(bd, 0);
6027    e_object_del(E_OBJECT(bd));
6028    return ECORE_CALLBACK_PASS_ON;
6029 }
6030
6031 static Eina_Bool
6032 _e_border_cb_window_hide(void *data  __UNUSED__,
6033                          int ev_type __UNUSED__,
6034                          void       *ev)
6035 {
6036    E_Border *bd = NULL;
6037    Ecore_X_Event_Window_Hide *e;
6038
6039    e = ev;
6040 //   printf("HIDE: %x, event %x send: %i\n", e->win, e->event_win, e->send_event);
6041 // not interested in hide events from windows other than the window in question
6042    if (e->win != e->event_win)
6043      {
6044         bd = e_border_find_by_client_window(e->win);
6045         if (!bd) return ECORE_CALLBACK_PASS_ON;
6046         if (!e->send_event) return ECORE_CALLBACK_PASS_ON;
6047         else
6048           {
6049              if (!((bd->zone) &&
6050                    (bd->zone->container->manager->root == e->event_win)))
6051                return ECORE_CALLBACK_PASS_ON;
6052           }
6053      }
6054    if (!bd) bd = e_border_find_by_client_window(e->win);
6055 //   printf("  bd = %p\n", bd);
6056    if (!bd)
6057      {
6058         if (ecore_x_window_visible_get(e->win))
6059           {
6060              ELB(ELBT_BD, "FORCE UNMAP client window", e->win);
6061              ecore_x_window_hide(e->win);
6062           }
6063         return ECORE_CALLBACK_PASS_ON;
6064      }
6065
6066 //   printf("  bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap);
6067    if (bd->ignore_first_unmap > 0)
6068      {
6069         bd->ignore_first_unmap--;
6070         return ECORE_CALLBACK_PASS_ON;
6071      }
6072    /* Don't delete hidden or iconified windows */
6073 #ifdef _F_USE_EXTENDED_ICONIFY_
6074    if (bd->await_hide_event > 0)
6075 #else
6076    if ((bd->iconic) || (bd->await_hide_event > 0))
6077 #endif
6078      {
6079 //        printf("  Don't delete hidden or iconified windows\n");
6080 //        printf("  bd->iconic = %i, bd->visible = %i, bd->new_client = %i, bd->await_hide_event = %i\n",
6081 //               bd->iconic, bd->visible, bd->new_client, bd->await_hide_event);
6082         if (bd->await_hide_event > 0)
6083           {
6084              bd->await_hide_event--;
6085           }
6086         else
6087           {
6088 //             printf("  hide really\n");
6089              /* Only hide the border if it is visible */
6090              if (bd->visible) e_border_hide(bd, 1);
6091           }
6092      }
6093    else
6094      {
6095 //             printf("  hide2\n");
6096 #ifdef _F_USE_EXTENDED_ICONIFY_
6097         if (bd->iconic)
6098           {
6099              bd->iconic = 0;
6100              bd->visible = 1;
6101           }
6102 #endif
6103
6104 #ifdef _F_ZONE_WINDOW_ROTATION_
6105         if (e_config->wm_win_rotation)
6106           {
6107              if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
6108                {
6109                   ELB(ELBT_BD, "X_UNMAP_NOTIFY", bd->client.win);
6110                   if (!rot.vkbd_hide_prepare_timer)
6111                     {
6112                        ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
6113                        e_border_hide(bd, 0);
6114                        if (!rot.vkbd_hide_prepare_timer)
6115                          {
6116                             ELB(ELBT_BD, "DEL VKBD", bd->client.win);
6117                             e_object_del(E_OBJECT(bd));
6118                          }
6119                     }
6120                   return ECORE_CALLBACK_PASS_ON;
6121                }
6122           }
6123 #endif
6124         e_border_hide(bd, 0);
6125         e_object_del(E_OBJECT(bd));
6126      }
6127    return ECORE_CALLBACK_PASS_ON;
6128 }
6129
6130 static Eina_Bool
6131 _e_border_cb_window_reparent(void *data  __UNUSED__,
6132                              int ev_type __UNUSED__,
6133                              void *ev    __UNUSED__)
6134 {
6135 #if 0
6136    E_Border *bd;
6137    Ecore_X_Event_Window_Reparent *e;
6138
6139    e = ev;
6140    bd = e_border_find_by_client_window(e->win);
6141    if (!bd) return 1;
6142    if (e->parent == bd->client.shell_win) return 1;
6143    if (ecore_x_window_parent_get(e->win) == bd->client.shell_win)
6144      {
6145         return 1;
6146      }
6147    e_border_hide(bd, 0);
6148    e_object_del(E_OBJECT(bd));
6149 #endif
6150    return ECORE_CALLBACK_PASS_ON;
6151 }
6152
6153 static Eina_Bool
6154 _e_border_cb_window_configure_request(void *data  __UNUSED__,
6155                                       int ev_type __UNUSED__,
6156                                       void       *ev)
6157 {
6158    E_Border *bd;
6159    Ecore_X_Event_Window_Configure_Request *e;
6160
6161    e = ev;
6162    bd = e_border_find_by_client_window(e->win);
6163    if (!bd)
6164      {
6165         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6166         if (!e_util_container_window_find(e->win))
6167           ecore_x_window_configure(e->win, e->value_mask,
6168                                    e->x, e->y, e->w, e->h, e->border,
6169                                    e->abovewin, e->detail);
6170         return ECORE_CALLBACK_PASS_ON;
6171      }
6172
6173    if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
6174        (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
6175      {
6176         int x, y;
6177
6178         x = bd->x;
6179         y = bd->y;
6180         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
6181           x = e->x;
6182         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
6183           y = e->y;
6184         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6185             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6186           {
6187              int w, h;
6188
6189              h = bd->h;
6190              w = bd->w;
6191              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6192                w = e->w + bd->client_inset.l + bd->client_inset.r;
6193              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6194                h = e->h + bd->client_inset.t + bd->client_inset.b;
6195              if ((!bd->lock_client_location) && (!bd->lock_client_size))
6196                {
6197                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6198                     {
6199                        bd->saved.x = x - bd->zone->x;
6200                        bd->saved.y = y - bd->zone->y;
6201                        bd->saved.w = w;
6202                        bd->saved.h = h;
6203                     }
6204                   else
6205                     e_border_move_resize(bd, x, y, w, h);
6206                }
6207              else if (!bd->lock_client_location)
6208                {
6209                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6210                     {
6211                        bd->saved.x = x - bd->zone->x;
6212                        bd->saved.y = y - bd->zone->y;
6213                     }
6214                   else
6215                     e_border_move(bd, x, y);
6216                }
6217              else if (!bd->lock_client_size)
6218                {
6219                   if ((bd->shaded) || (bd->shading))
6220                     {
6221                        int pw, ph;
6222
6223                        pw = bd->client.w;
6224                        ph = bd->client.h;
6225                        if ((bd->shade.dir == E_DIRECTION_UP) ||
6226                            (bd->shade.dir == E_DIRECTION_DOWN))
6227                          {
6228                             e_border_resize(bd, w, bd->h);
6229                             bd->client.h = ph;
6230                          }
6231                        else
6232                          {
6233                             e_border_resize(bd, bd->w, h);
6234                             bd->client.w = pw;
6235                          }
6236                     }
6237                   else
6238                     {
6239                        if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6240                          {
6241                             bd->saved.w = w;
6242                             bd->saved.h = h;
6243                          }
6244                        else
6245                          e_border_resize(bd, w, h);
6246                     }
6247                }
6248           }
6249         else
6250           {
6251              if (!bd->lock_client_location)
6252                {
6253                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6254                     {
6255                        bd->saved.x = x - bd->zone->x;
6256                        bd->saved.y = y - bd->zone->y;
6257                     }
6258                   else
6259                     e_border_move(bd, x, y);
6260                }
6261           }
6262      }
6263    else if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6264             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6265      {
6266         int w, h;
6267
6268         h = bd->h;
6269         w = bd->w;
6270         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6271           w = e->w + bd->client_inset.l + bd->client_inset.r;
6272         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6273           h = e->h + bd->client_inset.t + bd->client_inset.b;
6274 #ifdef _F_ZONE_WINDOW_ROTATION_
6275         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
6276 #endif
6277         if (!bd->lock_client_size)
6278           {
6279              if ((bd->shaded) || (bd->shading))
6280                {
6281                   int pw, ph;
6282
6283                   pw = bd->client.w;
6284                   ph = bd->client.h;
6285                   if ((bd->shade.dir == E_DIRECTION_UP) ||
6286                       (bd->shade.dir == E_DIRECTION_DOWN))
6287                     {
6288                        e_border_resize(bd, w, bd->h);
6289                        bd->client.h = ph;
6290                     }
6291                   else
6292                     {
6293                        e_border_resize(bd, bd->w, h);
6294                        bd->client.w = pw;
6295                     }
6296                }
6297              else
6298                {
6299                   if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE)
6300                     {
6301                        int zx, zy, zw, zh;
6302                        int rx = bd->x;
6303                        int ry = bd->y;
6304                        zx = zy = zw = zh = 0;
6305
6306      /*
6307       * This code does resize and move a window on a
6308       * X configure request into an useful geometry.
6309       * This is really useful for size jumping file dialogs.
6310       */
6311
6312                        if (bd->zone)
6313                          {
6314                             e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
6315
6316                             if (e_config->geometry_auto_resize_limit == 1)
6317                               {
6318                                  if (w > zw)
6319                                    w = zw;
6320
6321                                  if (h > zh)
6322                                    h = zh;
6323                               }
6324                          }
6325                        e_border_resize(bd, w, h);
6326
6327                        if (e_config->geometry_auto_move == 1)
6328                          {
6329                              /* z{x,y,w,h} are only set here; FIXME! */
6330                              if (bd->zone)
6331                                {
6332                                   // move window horizontal if resize to not useful geometry
6333                                   if (bd->x + bd->w > zx + zw)
6334                                     rx = zx + zw - bd->w;
6335                                   else if (bd->x < zx)
6336                                     rx = zx;
6337
6338                                   // move window vertical if resize to not useful geometry
6339                                   if (bd->y + bd->h > zy + zh)
6340                                     ry = zy + zh - bd->h;
6341                                   else if (bd->y < zy)
6342                                     ry = zy;
6343                                }
6344                              e_border_move(bd, rx, ry);
6345                          }
6346                     }
6347                }
6348           }
6349      }
6350    if (!bd->lock_client_stacking)
6351      {
6352         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
6353             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
6354           {
6355              E_Border *obd;
6356
6357              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6358                {
6359                   obd = e_border_find_by_client_window(e->abovewin);
6360                   if (obd)
6361                     {
6362                        e_border_stack_above(bd, obd);
6363                     }
6364                   else
6365                     {
6366                        ecore_x_window_configure(bd->win,
6367                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6368                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6369                                                 0, 0, 0, 0, 0,
6370                                                 e->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
6371                        /* FIXME: need to rebuiuld border list from current stacking */
6372                     }
6373                }
6374              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6375                {
6376                   obd = e_border_find_by_client_window(e->abovewin);
6377                   if (obd)
6378                     {
6379                        e_border_stack_below(bd, obd);
6380                     }
6381                   else
6382                     {
6383                        ecore_x_window_configure(bd->win,
6384                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6385                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6386                                                 0, 0, 0, 0, 0,
6387                                                 e->abovewin, ECORE_X_WINDOW_STACK_BELOW);
6388                        /* FIXME: need to rebuiuld border list from current stacking */
6389                     }
6390                }
6391              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6392                {
6393      /* FIXME: do */
6394                }
6395              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6396                {
6397      /* FIXME: do */
6398                }
6399              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6400                {
6401      /* FIXME: do */
6402                }
6403           }
6404         else if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
6405           {
6406              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6407                {
6408                   e_border_raise(bd);
6409                }
6410              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6411                {
6412                   e_border_lower(bd);
6413                }
6414              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6415                {
6416      /* FIXME: do */
6417                }
6418              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6419                {
6420      /* FIXME: do */
6421                }
6422              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6423                {
6424      /* FIXME: do */
6425                }
6426           }
6427      }
6428
6429    /* FIXME: need to send synthetic stacking event too as well as move/resize */
6430    _e_border_client_move_resize_send(bd);
6431    return ECORE_CALLBACK_PASS_ON;
6432 }
6433
6434 static Eina_Bool
6435 _e_border_cb_window_resize_request(void *data  __UNUSED__,
6436                                    int ev_type __UNUSED__,
6437                                    void       *ev)
6438 {
6439    E_Border *bd;
6440    Ecore_X_Event_Window_Resize_Request *e;
6441
6442    e = ev;
6443    bd = e_border_find_by_client_window(e->win);
6444    if (!bd)
6445      {
6446         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6447         ecore_x_window_resize(e->win, e->w, e->h);
6448         return ECORE_CALLBACK_PASS_ON;
6449      }
6450    {
6451       int w, h;
6452
6453       w = e->w + bd->client_inset.l + bd->client_inset.r;
6454       h = e->h + bd->client_inset.t + bd->client_inset.b;
6455       if ((bd->shaded) || (bd->shading))
6456         {
6457            int pw, ph;
6458
6459            pw = bd->client.w;
6460            ph = bd->client.h;
6461            if ((bd->shade.dir == E_DIRECTION_UP) ||
6462                (bd->shade.dir == E_DIRECTION_DOWN))
6463              {
6464                 e_border_resize(bd, w, bd->h);
6465                 bd->client.h = ph;
6466              }
6467            else
6468              {
6469                 e_border_resize(bd, bd->w, h);
6470                 bd->client.w = pw;
6471              }
6472         }
6473       else
6474         e_border_resize(bd, w, h);
6475    }
6476
6477    _e_border_client_move_resize_send(bd);
6478    return ECORE_CALLBACK_PASS_ON;
6479 }
6480
6481 static Eina_Bool
6482 _e_border_cb_window_gravity(void *data  __UNUSED__,
6483                             int ev_type __UNUSED__,
6484                             void *ev    __UNUSED__)
6485 {
6486 //   E_Border *bd;
6487 //   Ecore_X_Event_Window_Gravity *e;
6488
6489 //   e = ev;
6490 //   bd = e_border_find_by_client_window(e->win);
6491 //   if (!bd) return 1;
6492              return 1;
6493 }
6494
6495 static Eina_Bool
6496 _e_border_cb_window_stack_request(void *data  __UNUSED__,
6497                                   int ev_type __UNUSED__,
6498                                   void       *ev)
6499 {
6500    E_Border *bd;
6501    Ecore_X_Event_Window_Stack_Request *e;
6502
6503    e = ev;
6504    bd = e_border_find_by_client_window(e->win);
6505    if (!bd)
6506      {
6507         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6508         if (!e_util_container_window_find(e->win))
6509           {
6510              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6511                ecore_x_window_raise(e->win);
6512              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6513                ecore_x_window_lower(e->win);
6514           }
6515         return ECORE_CALLBACK_PASS_ON;
6516      }
6517    if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6518      e_border_raise(bd);
6519    else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6520      e_border_lower(bd);
6521    return ECORE_CALLBACK_PASS_ON;
6522 }
6523
6524 static Eina_Bool
6525 _e_border_cb_window_property(void *data  __UNUSED__,
6526                              int ev_type __UNUSED__,
6527                              void       *ev)
6528 {
6529    E_Border *bd;
6530    Ecore_X_Event_Window_Property *e;
6531
6532    e = ev;
6533    bd = e_border_find_by_client_window(e->win);
6534    if (!bd) return ECORE_CALLBACK_PASS_ON;
6535    if (e->atom == ECORE_X_ATOM_WM_NAME)
6536      {
6537         if ((!bd->client.netwm.name) &&
6538             (!bd->client.netwm.fetch.name))
6539           {
6540              bd->client.icccm.fetch.title = 1;
6541              bd->changed = 1;
6542           }
6543      }
6544    else if (e->atom == ECORE_X_ATOM_NET_WM_NAME)
6545      {
6546         bd->client.netwm.fetch.name = 1;
6547         bd->changed = 1;
6548      }
6549    else if (e->atom == ECORE_X_ATOM_WM_CLASS)
6550      {
6551         bd->client.icccm.fetch.name_class = 1;
6552         bd->changed = 1;
6553      }
6554    else if (e->atom == ECORE_X_ATOM_WM_ICON_NAME)
6555      {
6556         if ((!bd->client.netwm.icon_name) &&
6557             (!bd->client.netwm.fetch.icon_name))
6558           {
6559              bd->client.icccm.fetch.icon_name = 1;
6560              bd->changed = 1;
6561           }
6562      }
6563    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
6564      {
6565         bd->client.netwm.fetch.icon_name = 1;
6566         bd->changed = 1;
6567      }
6568    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
6569      {
6570         bd->client.icccm.fetch.machine = 1;
6571         bd->changed = 1;
6572      }
6573    else if (e->atom == ECORE_X_ATOM_WM_PROTOCOLS)
6574      {
6575         bd->client.icccm.fetch.protocol = 1;
6576         bd->changed = 1;
6577      }
6578    else if (e->atom == ECORE_X_ATOM_WM_HINTS)
6579      {
6580         bd->client.icccm.fetch.hints = 1;
6581         bd->changed = 1;
6582      }
6583    else if (e->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
6584      {
6585         bd->client.icccm.fetch.size_pos_hints = 1;
6586         bd->changed = 1;
6587      }
6588    else if (e->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
6589      {
6590         /*
6591            if ((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN) &&
6592             (!bd->client.netwm.fetch.type))
6593            {
6594          */
6595           bd->client.mwm.fetch.hints = 1;
6596           bd->changed = 1;
6597           /*
6598              }
6599            */
6600      }
6601    else if (e->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
6602      {
6603         bd->client.icccm.fetch.transient_for = 1;
6604         bd->changed = 1;
6605      }
6606    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
6607      {
6608         bd->client.icccm.fetch.client_leader = 1;
6609         bd->changed = 1;
6610      }
6611    else if (e->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
6612      {
6613         bd->client.icccm.fetch.window_role = 1;
6614         bd->changed = 1;
6615      }
6616    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON)
6617      {
6618         bd->client.netwm.fetch.icon = 1;
6619         bd->changed = 1;
6620      }
6621    else if (e->atom == ATM__QTOPIA_SOFT_MENU)
6622      {
6623         bd->client.qtopia.fetch.soft_menu = 1;
6624         bd->changed = 1;
6625      }
6626    else if (e->atom == ATM__QTOPIA_SOFT_MENUS)
6627      {
6628         bd->client.qtopia.fetch.soft_menus = 1;
6629         bd->changed = 1;
6630      }
6631    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
6632      {
6633         bd->client.vkbd.fetch.state = 1;
6634         bd->changed = 1;
6635      }
6636    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
6637      {
6638         bd->client.vkbd.fetch.vkbd = 1;
6639         bd->changed = 1;
6640      }
6641    else if (e->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
6642      {
6643         bd->client.illume.conformant.fetch.conformant = 1;
6644         bd->changed = 1;
6645      }
6646    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
6647      {
6648         bd->client.illume.quickpanel.fetch.state = 1;
6649         bd->changed = 1;
6650      }
6651    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
6652      {
6653         bd->client.illume.quickpanel.fetch.quickpanel = 1;
6654         bd->changed = 1;
6655      }
6656    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
6657      {
6658         bd->client.illume.quickpanel.fetch.priority.major = 1;
6659         bd->changed = 1;
6660      }
6661    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
6662      {
6663         bd->client.illume.quickpanel.fetch.priority.minor = 1;
6664         bd->changed = 1;
6665      }
6666    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
6667      {
6668         bd->client.illume.quickpanel.fetch.zone = 1;
6669         bd->changed = 1;
6670      }
6671    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
6672      {
6673         bd->client.illume.drag.fetch.locked = 1;
6674         bd->changed = 1;
6675      }
6676    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
6677      {
6678         bd->client.illume.drag.fetch.drag = 1;
6679         bd->changed = 1;
6680      }
6681    else if (e->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
6682      {
6683         bd->client.illume.win_state.fetch.state = 1;
6684         bd->changed = 1;
6685      }
6686    /*
6687       else if (e->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
6688       {
6689         bd->client.netwm.fetch.user_time = 1;
6690         bd->changed = 1;
6691       }
6692       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT)
6693       {
6694         bd->client.netwm.fetch.strut = 1;
6695         bd->changed = 1;
6696       }
6697       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
6698       {
6699         bd->client.netwm.fetch.strut = 1;
6700         bd->changed = 1;
6701       }
6702     */
6703    else if (e->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
6704      {
6705         //printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
6706      }
6707    else if (e->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
6708      {
6709         bd->client.e.fetch.video_position = 1;
6710         bd->changed = 1;
6711      }
6712    else if (e->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
6713      {
6714         bd->client.e.fetch.video_parent = 1;
6715         bd->changed = 1;
6716      }
6717    else if (e->atom == ECORE_X_ATOM_NET_WM_STATE)
6718      {
6719         bd->client.netwm.fetch.state = 1;
6720         bd->changed = 1;
6721      }
6722 #ifdef _F_USE_DESK_WINDOW_PROFILE_
6723    else if (e->atom == ECORE_X_ATOM_E_PROFILE_LIST)
6724      {
6725         bd->client.e.fetch.profile_list = 1;
6726         bd->changed = 1;
6727      }
6728 #endif
6729 #ifdef _F_ZONE_WINDOW_ROTATION_
6730    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED)
6731      {
6732         if (e_config->wm_win_rotation)
6733           {
6734              bd->client.e.fetch.rot.support = 1;
6735              bd->changed = 1;
6736           }
6737      }
6738    else if ((e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) ||
6739             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) ||
6740             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) ||
6741             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY))
6742      {
6743         if (e_config->wm_win_rotation)
6744           {
6745              bd->client.e.fetch.rot.geom_hint = 1;
6746              bd->changed = 1;
6747           }
6748      }
6749    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED)
6750      {
6751         if (e_config->wm_win_rotation)
6752           {
6753              bd->client.e.fetch.rot.app_set = 1;
6754              bd->changed = 1;
6755           }
6756      }
6757    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION)
6758      {
6759         if (e_config->wm_win_rotation)
6760           {
6761              bd->client.e.fetch.rot.preferred_rot = 1;
6762              bd->changed = 1;
6763           }
6764      }
6765    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)
6766      {
6767         if (e_config->wm_win_rotation)
6768           {
6769              bd->client.e.fetch.rot.available_rots = 1;
6770              bd->changed = 1;
6771           }
6772      }
6773 #endif
6774
6775    return ECORE_CALLBACK_PASS_ON;
6776 }
6777
6778 static Eina_Bool
6779 _e_border_cb_window_colormap(void *data  __UNUSED__,
6780                              int ev_type __UNUSED__,
6781                              void       *ev)
6782 {
6783    E_Border *bd;
6784    Ecore_X_Event_Window_Colormap *e;
6785
6786    e = ev;
6787    bd = e_border_find_by_client_window(e->win);
6788    if (!bd) return ECORE_CALLBACK_PASS_ON;
6789    return ECORE_CALLBACK_PASS_ON;
6790 }
6791
6792 static Eina_Bool
6793 _e_border_cb_window_shape(void *data  __UNUSED__,
6794                           int ev_type __UNUSED__,
6795                           void       *ev)
6796 {
6797    E_Border *bd;
6798    Ecore_X_Event_Window_Shape *e;
6799
6800    e = ev;
6801    bd = e_border_find_by_client_window(e->win);
6802
6803    if (e->type == ECORE_X_SHAPE_INPUT)
6804      {
6805         if (bd)
6806           {
6807              bd->need_shape_merge = 1;
6808 // YYY             bd->shaped_input = 1;
6809              bd->changes.shape_input = 1;
6810              bd->changed = 1;
6811           }
6812
6813         return ECORE_CALLBACK_PASS_ON;
6814      }
6815
6816    if (bd)
6817      {
6818         bd->changes.shape = 1;
6819         bd->changed = 1;
6820         return ECORE_CALLBACK_PASS_ON;
6821      }
6822    bd = e_border_find_by_window(e->win);
6823    if (bd)
6824      {
6825         bd->need_shape_export = 1;
6826         bd->changed = 1;
6827         return ECORE_CALLBACK_PASS_ON;
6828      }
6829    bd = e_border_find_by_frame_window(e->win);
6830    if (bd)
6831      {
6832         bd->need_shape_merge = 1;
6833         bd->changed = 1;
6834         return ECORE_CALLBACK_PASS_ON;
6835      }
6836    return ECORE_CALLBACK_PASS_ON;
6837 }
6838
6839 static Eina_Bool
6840 _e_border_cb_window_focus_in(void *data  __UNUSED__,
6841                              int ev_type __UNUSED__,
6842                              void       *ev)
6843 {
6844    E_Border *bd;
6845    Ecore_X_Event_Window_Focus_In *e;
6846
6847    e = ev;
6848    bd = e_border_find_by_client_window(e->win);
6849    if (!bd) return ECORE_CALLBACK_PASS_ON;
6850 #ifdef INOUTDEBUG_FOCUS
6851    {
6852       time_t t;
6853       char *ct;
6854
6855       const char *modes[] = {
6856         "MODE_NORMAL",
6857         "MODE_WHILE_GRABBED",
6858         "MODE_GRAB",
6859         "MODE_UNGRAB"
6860       };
6861       const char *details[] = {
6862         "DETAIL_ANCESTOR",
6863         "DETAIL_VIRTUAL",
6864         "DETAIL_INFERIOR",
6865         "DETAIL_NON_LINEAR",
6866         "DETAIL_NON_LINEAR_VIRTUAL",
6867         "DETAIL_POINTER",
6868         "DETAIL_POINTER_ROOT",
6869         "DETAIL_DETAIL_NONE"
6870       };
6871       t = time(NULL);
6872       ct = ctime(&t);
6873       ct[strlen(ct) - 1] = 0;
6874       DBG("FF ->IN %i 0x%x %s md=%s dt=%s\n",
6875              e->time,
6876              e->win,
6877              ct,
6878              modes[e->mode],
6879              details[e->detail]);
6880
6881       DBG("%s cb focus in %d %d\n",
6882              e_border_name_get(bd),
6883              bd->client.icccm.accepts_focus,
6884              bd->client.icccm.take_focus);
6885    }
6886 #endif
6887    _e_border_pri_raise(bd);
6888    if (e->mode == ECORE_X_EVENT_MODE_GRAB)
6889      {
6890         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
6891      }
6892    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
6893      {
6894         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
6895      }
6896
6897    /* ignore focus in from !take_focus windows, we just gave it em */
6898    /* if (!bd->client.icccm.take_focus)
6899     *   return ECORE_CALLBACK_PASS_ON; */
6900
6901    /* should be equal, maybe some clients dont reply with the proper timestamp ? */
6902    if (e->time >= focus_time)
6903      e_border_focus_set(bd, 1, 0);
6904    return ECORE_CALLBACK_PASS_ON;
6905 }
6906
6907 static Eina_Bool
6908 _e_border_cb_window_focus_out(void *data  __UNUSED__,
6909                               int ev_type __UNUSED__,
6910                               void       *ev)
6911 {
6912    E_Border *bd;
6913    Ecore_X_Event_Window_Focus_Out *e;
6914
6915    e = ev;
6916    bd = e_border_find_by_client_window(e->win);
6917    if (!bd) return ECORE_CALLBACK_PASS_ON;
6918 #ifdef INOUTDEBUG_FOCUS
6919    {
6920       time_t t;
6921       char *ct;
6922
6923       const char *modes[] = {
6924         "MODE_NORMAL",
6925         "MODE_WHILE_GRABBED",
6926         "MODE_GRAB",
6927         "MODE_UNGRAB"
6928       };
6929       const char *details[] = {
6930         "DETAIL_ANCESTOR",
6931         "DETAIL_VIRTUAL",
6932         "DETAIL_INFERIOR",
6933         "DETAIL_NON_LINEAR",
6934         "DETAIL_NON_LINEAR_VIRTUAL",
6935         "DETAIL_POINTER",
6936         "DETAIL_POINTER_ROOT",
6937         "DETAIL_DETAIL_NONE"
6938       };
6939       t = time(NULL);
6940       ct = ctime(&t);
6941       ct[strlen(ct) - 1] = 0;
6942       DBG("FF <-OUT %i 0x%x %s md=%s dt=%s",
6943              e->time,
6944              e->win,
6945              ct,
6946              modes[e->mode],
6947              details[e->detail]);
6948
6949       DBG("%s cb focus out %d %d",
6950              e_border_name_get(bd),
6951              bd->client.icccm.accepts_focus,
6952              bd->client.icccm.take_focus);
6953    }
6954 #endif
6955    _e_border_pri_norm(bd);
6956    if (e->mode == ECORE_X_EVENT_MODE_NORMAL)
6957      {
6958         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
6959         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
6960           return ECORE_CALLBACK_PASS_ON;
6961         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
6962           return ECORE_CALLBACK_PASS_ON;
6963      }
6964    else if (e->mode == ECORE_X_EVENT_MODE_GRAB)
6965      {
6966         if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR) return ECORE_CALLBACK_PASS_ON;
6967         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
6968           return ECORE_CALLBACK_PASS_ON;
6969         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
6970           return ECORE_CALLBACK_PASS_ON;
6971         else if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
6972           return ECORE_CALLBACK_PASS_ON;
6973         else if (e->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
6974           return ECORE_CALLBACK_PASS_ON;
6975      }
6976    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
6977      {
6978         /* for firefox/thunderbird (xul) menu walking */
6979         /* NB: why did i disable this before? */
6980         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
6981         else if (e->detail == ECORE_X_EVENT_DETAIL_POINTER)
6982           return ECORE_CALLBACK_PASS_ON;
6983      }
6984    else if (e->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
6985      {
6986         if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR) return ECORE_CALLBACK_PASS_ON;
6987         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
6988           return ECORE_CALLBACK_PASS_ON;
6989      }
6990    e_border_focus_set(bd, 0, 0);
6991    return ECORE_CALLBACK_PASS_ON;
6992 }
6993
6994 #if _F_BORDER_CLIP_TO_ZONE_
6995 static void
6996 _e_border_shape_input_clip_to_zone(E_Border *bd)
6997 {
6998    /* if (!(e_config->window_out_of_vscreen_limits_partly)) return; */
6999    if (!(bd->visible))
7000      return;
7001
7002    if (!(E_CONTAINS(bd->zone->x, bd->zone->y,
7003                     bd->zone->w, bd->zone->h,
7004                     bd->x, bd->y, bd->w, bd->h)))
7005      {
7006         int x, y, w, h;
7007         x = bd->x; y = bd->y; w = bd->w; h = bd->h;
7008         E_RECTS_CLIP_TO_RECT(x, y, w, h,
7009                              bd->zone->x, bd->zone->y,
7010                              bd->zone->w, bd->zone->h);
7011         x -= bd->x;
7012         y -= bd->y;
7013         ecore_x_window_shape_input_rectangle_set(bd->bg_win, x, y, w, h);
7014         ecore_x_window_shape_input_rectangle_set(bd->win, x, y, w, h);
7015      }
7016    else
7017      {
7018         ecore_x_window_shape_input_rectangle_set(bd->bg_win, 0, 0, bd->w, bd->h);
7019         ecore_x_window_shape_input_rectangle_set(bd->win, 0, 0, bd->w, bd->h);
7020      }
7021 }
7022 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
7023
7024 static Eina_Bool
7025 _e_border_cb_client_message(void *data  __UNUSED__,
7026                             int ev_type __UNUSED__,
7027                             void       *ev)
7028 {
7029    Ecore_X_Event_Client_Message *e;
7030    E_Border *bd;
7031
7032    e = ev;
7033 #ifdef _F_DEICONIFY_APPROVE_
7034    if (e->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
7035      {
7036         if (!e_config->deiconify_approve) return ECORE_CALLBACK_PASS_ON;
7037
7038         bd = e_border_find_by_client_window(e->win);
7039         if (bd)
7040           {
7041              if (bd->client.e.state.deiconify_approve.support)
7042                {
7043                   if (e->data.l[1] != 1) return ECORE_CALLBACK_PASS_ON;
7044                   bd->client.e.state.deiconify_approve.render_done = 1;
7045
7046                   E_Border *ancestor_bd;
7047                   ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
7048                   if (ancestor_bd)
7049                     {
7050                        ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
7051                        bd->client.e.state.deiconify_approve.ancestor = NULL;
7052                     }
7053                   else
7054                     {
7055                        ancestor_bd = bd;
7056                     }
7057
7058                   ELBF(ELBT_BD, 0, bd->client.win,
7059                        "RECEIVE DEICONIFY_APPROVE.. ancestor:%x", ancestor_bd->client.win);
7060
7061                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
7062                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
7063                     {
7064                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
7065                          {
7066                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
7067                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
7068                             e_border_uniconify(ancestor_bd);
7069                          }
7070                        else
7071                          {
7072                             ELB(ELBT_BD, "Unset DEICONIFY_APPROVE render_done", ancestor_bd->client.win);
7073                             ancestor_bd->client.e.state.deiconify_approve.render_done = 0;
7074                          }
7075                     }
7076                }
7077           }
7078         return ECORE_CALLBACK_PASS_ON;
7079      }
7080 #endif
7081
7082 #ifdef _F_ZONE_WINDOW_ROTATION_
7083    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
7084
7085    bd = e_border_find_by_client_window(e->win);
7086    if (!bd)
7087      {
7088         if (e_config->wm_win_rotation)
7089           {
7090              Ecore_X_Event_Client_Message *msg = NULL;
7091              Ecore_X_Atom t = e->message_type;
7092              if ((t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)  ||
7093                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE) ||
7094                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)   ||
7095                  (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE))
7096                {
7097                   msg = E_NEW(Ecore_X_Event_Client_Message, 1);
7098                   if (!msg) return ECORE_CALLBACK_PASS_ON;
7099
7100                   msg->win = e->win;
7101                   msg->message_type = e->message_type;
7102                   msg->data.l[0] = e->data.l[0];
7103                   msg->data.l[1] = e->data.l[1];
7104                   msg->data.l[2] = e->data.l[2];
7105                   msg->data.l[3] = e->data.l[3];
7106                   msg->data.l[4] = e->data.l[4];
7107                   rot.msgs = eina_list_append(rot.msgs, msg);
7108
7109                   rot.fetch = EINA_TRUE;
7110                }
7111           }
7112         return ECORE_CALLBACK_PASS_ON;
7113      }
7114
7115    if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE)
7116      {
7117         ELBF(ELBT_ROT, 0, e->data.l[0], "GET ROT_DONE a%d %dx%d zone_a:%d",
7118              e->data.l[1], e->data.l[2], e->data.l[3], bd->zone->rot.curr);
7119
7120         if (e_config->wm_win_rotation)
7121           {
7122              if ((int)e->data.l[1] == bd->client.e.state.rot.curr)
7123                {
7124                   _e_border_rotation_list_remove(bd);
7125                   if (bd->client.e.state.rot.pending_show)
7126                     {
7127                        ELB(ELBT_BD, "SHOW_BD (PEND)", bd->client.win);
7128                        e_border_show(bd);
7129 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
7130                        if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
7131                          _e_border_check_stack(bd);
7132 #endif
7133                        bd->client.e.state.rot.pending_show = 0;
7134                     }
7135                }
7136           }
7137      }
7138 #endif
7139    return ECORE_CALLBACK_PASS_ON;
7140 }
7141
7142 static Eina_Bool
7143 _e_border_cb_window_state_request(void *data  __UNUSED__,
7144                                   int ev_type __UNUSED__,
7145                                   void       *ev)
7146 {
7147    E_Border *bd;
7148    Ecore_X_Event_Window_State_Request *e;
7149    int i;
7150
7151    e = ev;
7152    bd = e_border_find_by_client_window(e->win);
7153    if (!bd) return ECORE_CALLBACK_PASS_ON;
7154
7155    for (i = 0; i < 2; i++)
7156      e_hints_window_state_update(bd, e->state[i], e->action);
7157
7158    return ECORE_CALLBACK_PASS_ON;
7159 }
7160
7161 static Eina_Bool
7162 _e_border_cb_window_move_resize_request(void *data  __UNUSED__,
7163                                         int ev_type __UNUSED__,
7164                                         void       *ev)
7165 {
7166    E_Border *bd;
7167    Ecore_X_Event_Window_Move_Resize_Request *e;
7168
7169    e = ev;
7170    bd = e_border_find_by_client_window(e->win);
7171    if (!bd) return ECORE_CALLBACK_PASS_ON;
7172
7173    if ((bd->shaded) || (bd->shading) ||
7174        (bd->fullscreen) || (bd->moving) ||
7175        (bd->resize_mode != RESIZE_NONE))
7176      return ECORE_CALLBACK_PASS_ON;
7177
7178    if ((e->button >= 1) && (e->button <= 3))
7179      {
7180         bd->mouse.last_down[e->button - 1].mx = e->x;
7181         bd->mouse.last_down[e->button - 1].my = e->y;
7182         bd->mouse.last_down[e->button - 1].x = bd->x;
7183         bd->mouse.last_down[e->button - 1].y = bd->y;
7184         bd->mouse.last_down[e->button - 1].w = bd->w;
7185         bd->mouse.last_down[e->button - 1].h = bd->h;
7186      }
7187    else
7188      {
7189         bd->moveinfo.down.x = bd->x;
7190         bd->moveinfo.down.y = bd->y;
7191         bd->moveinfo.down.w = bd->w;
7192         bd->moveinfo.down.h = bd->h;
7193      }
7194    bd->mouse.current.mx = e->x;
7195    bd->mouse.current.my = e->y;
7196    bd->moveinfo.down.button = e->button;
7197    bd->moveinfo.down.mx = e->x;
7198    bd->moveinfo.down.my = e->y;
7199    grabbed = 1;
7200
7201    if (!bd->lock_user_stacking)
7202      e_border_raise(bd);
7203
7204    if (e->direction == MOVE)
7205      {
7206         bd->cur_mouse_action = e_action_find("window_move");
7207         if (bd->cur_mouse_action)
7208           {
7209              if ((!bd->cur_mouse_action->func.end_mouse) &&
7210                  (!bd->cur_mouse_action->func.end))
7211                bd->cur_mouse_action = NULL;
7212              if (bd->cur_mouse_action)
7213                {
7214                   e_object_ref(E_OBJECT(bd->cur_mouse_action));
7215                   bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
7216                }
7217           }
7218         return ECORE_CALLBACK_PASS_ON;
7219      }
7220
7221    if (!_e_border_resize_begin(bd))
7222      return ECORE_CALLBACK_PASS_ON;
7223
7224    switch (e->direction)
7225      {
7226       case RESIZE_TL:
7227         bd->resize_mode = RESIZE_TL;
7228         GRAV_SET(bd, ECORE_X_GRAVITY_SE);
7229         break;
7230
7231       case RESIZE_T:
7232         bd->resize_mode = RESIZE_T;
7233         GRAV_SET(bd, ECORE_X_GRAVITY_S);
7234         break;
7235
7236       case RESIZE_TR:
7237         bd->resize_mode = RESIZE_TR;
7238         GRAV_SET(bd, ECORE_X_GRAVITY_SW);
7239         break;
7240
7241       case RESIZE_R:
7242         bd->resize_mode = RESIZE_R;
7243         GRAV_SET(bd, ECORE_X_GRAVITY_W);
7244         break;
7245
7246       case RESIZE_BR:
7247         bd->resize_mode = RESIZE_BR;
7248         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
7249         break;
7250
7251       case RESIZE_B:
7252         bd->resize_mode = RESIZE_B;
7253         GRAV_SET(bd, ECORE_X_GRAVITY_N);
7254         break;
7255
7256       case RESIZE_BL:
7257         bd->resize_mode = RESIZE_BL;
7258         GRAV_SET(bd, ECORE_X_GRAVITY_NE);
7259         break;
7260
7261       case RESIZE_L:
7262         bd->resize_mode = RESIZE_L;
7263         GRAV_SET(bd, ECORE_X_GRAVITY_E);
7264         break;
7265
7266       default:
7267         return ECORE_CALLBACK_PASS_ON;
7268      }
7269
7270    bd->cur_mouse_action = e_action_find("window_resize");
7271    if (bd->cur_mouse_action)
7272      {
7273         if ((!bd->cur_mouse_action->func.end_mouse) &&
7274             (!bd->cur_mouse_action->func.end))
7275           bd->cur_mouse_action = NULL;
7276      }
7277    if (bd->cur_mouse_action)
7278      e_object_ref(E_OBJECT(bd->cur_mouse_action));
7279
7280    return ECORE_CALLBACK_PASS_ON;
7281 }
7282
7283 static Eina_Bool
7284 _e_border_cb_desktop_change(void *data  __UNUSED__,
7285                             int ev_type __UNUSED__,
7286                             void       *ev)
7287 {
7288    E_Border *bd;
7289    Ecore_X_Event_Desktop_Change *e;
7290
7291    e = ev;
7292    bd = e_border_find_by_client_window(e->win);
7293    if (bd)
7294      {
7295         if (e->desk == 0xffffffff)
7296           e_border_stick(bd);
7297         else if ((int)e->desk < (bd->zone->desk_x_count * bd->zone->desk_y_count))
7298           {
7299              E_Desk *desk;
7300
7301              desk = e_desk_at_pos_get(bd->zone, e->desk);
7302              if (desk)
7303                e_border_desk_set(bd, desk);
7304           }
7305      }
7306    else
7307      {
7308         ecore_x_netwm_desktop_set(e->win, e->desk);
7309      }
7310    return ECORE_CALLBACK_PASS_ON;
7311 }
7312
7313 static Eina_Bool
7314 _e_border_cb_sync_alarm(void *data  __UNUSED__,
7315                         int ev_type __UNUSED__,
7316                         void       *ev)
7317 {
7318    E_Border *bd;
7319    Ecore_X_Event_Sync_Alarm *e;
7320    unsigned int serial;
7321
7322    e = ev;
7323    bd = e_border_find_by_alarm(e->alarm);
7324    if (!bd) return ECORE_CALLBACK_PASS_ON;
7325
7326    if (bd->client.netwm.sync.wait)
7327      bd->client.netwm.sync.wait--;
7328
7329    if (ecore_x_sync_counter_query(bd->client.netwm.sync.counter, &serial))
7330      {
7331         E_Border_Pending_Move_Resize *pnd = NULL;
7332
7333         /* skip pending for which we didn't get a reply */
7334         while (bd->pending_move_resize)
7335           {
7336              pnd = bd->pending_move_resize->data;
7337              bd->pending_move_resize = eina_list_remove(bd->pending_move_resize, pnd);
7338
7339              if (serial == pnd->serial)
7340                break;
7341
7342              E_FREE(pnd);
7343           }
7344
7345         if (pnd)
7346           {
7347              bd->x = pnd->x;
7348              bd->y = pnd->y;
7349              bd->w = pnd->w;
7350              bd->h = pnd->h;
7351              bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
7352              bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
7353              E_FREE(pnd);
7354           }
7355      }
7356
7357    bd->changes.size = 1;
7358    bd->changes.pos = 1;
7359
7360    _e_border_eval(bd);
7361    evas_render(bd->bg_evas);
7362
7363    ecore_x_pointer_xy_get(e_manager_current_get()->root,
7364                           &bd->mouse.current.mx,
7365                           &bd->mouse.current.my);
7366
7367    bd->client.netwm.sync.send_time = ecore_loop_time_get();
7368    _e_border_resize_handle(bd);
7369
7370    return ECORE_CALLBACK_PASS_ON;
7371 }
7372
7373 static Eina_Bool
7374 _e_border_cb_efreet_cache_update(void *data  __UNUSED__,
7375                                  int ev_type __UNUSED__,
7376                                  void *ev    __UNUSED__)
7377 {
7378    Eina_List *l;
7379    E_Border *bd;
7380
7381    /* mark all borders for desktop/icon updates */
7382    EINA_LIST_FOREACH(borders, l, bd)
7383      {
7384         if (bd->desktop)
7385           {
7386              efreet_desktop_free(bd->desktop);
7387              bd->desktop = NULL;
7388           }
7389         bd->changes.icon = 1;
7390         bd->changed = 1;
7391      }
7392    /*
7393       e_init_status_set(_("Desktop files scan done"));
7394       e_init_done();
7395     */
7396    return ECORE_CALLBACK_PASS_ON;
7397 }
7398
7399 static Eina_Bool
7400 _e_border_cb_config_icon_theme(void *data  __UNUSED__,
7401                                int ev_type __UNUSED__,
7402                                void *ev    __UNUSED__)
7403 {
7404    Eina_List *l;
7405    E_Border *bd;
7406
7407    /* mark all borders for desktop/icon updates */
7408    EINA_LIST_FOREACH(borders, l, bd)
7409      {
7410         bd->changes.icon = 1;
7411         bd->changed = 1;
7412      }
7413    return ECORE_CALLBACK_PASS_ON;
7414 }
7415
7416 static Eina_Bool
7417 _e_border_cb_pointer_warp(void *data  __UNUSED__,
7418                           int ev_type __UNUSED__,
7419                           void       *ev)
7420 {
7421    E_Event_Pointer_Warp *e;
7422
7423    e = ev;
7424    if (!bdmove) return ECORE_CALLBACK_PASS_ON;
7425    e_border_move(bdmove, bdmove->x + (e->curr.x - e->prev.x), bdmove->y + (e->curr.y - e->prev.y));
7426    return ECORE_CALLBACK_PASS_ON;
7427 }
7428
7429 static void
7430 _e_border_cb_signal_bind(void            *data,
7431                          Evas_Object *obj __UNUSED__,
7432                          const char      *emission,
7433                          const char      *source)
7434 {
7435    E_Border *bd;
7436
7437    bd = data;
7438    if (e_dnd_active()) return;
7439    e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd),
7440                             emission, source);
7441 }
7442
7443 static Eina_Bool
7444 _e_border_cb_mouse_in(void    *data,
7445                       int type __UNUSED__,
7446                       void    *event)
7447 {
7448    Ecore_X_Event_Mouse_In *ev;
7449    E_Border *bd;
7450
7451    ev = event;
7452    bd = data;
7453 #ifdef INOUTDEBUG_MOUSE
7454    {
7455       time_t t;
7456       char *ct;
7457
7458       const char *modes[] = {
7459          "MODE_NORMAL",
7460          "MODE_WHILE_GRABBED",
7461          "MODE_GRAB",
7462          "MODE_UNGRAB"
7463       };
7464       const char *details[] = {
7465          "DETAIL_ANCESTOR",
7466          "DETAIL_VIRTUAL",
7467          "DETAIL_INFERIOR",
7468          "DETAIL_NON_LINEAR",
7469          "DETAIL_NON_LINEAR_VIRTUAL",
7470          "DETAIL_POINTER",
7471          "DETAIL_POINTER_ROOT",
7472          "DETAIL_DETAIL_NONE"
7473       };
7474       t = time(NULL);
7475       ct = ctime(&t);
7476       ct[strlen(ct) - 1] = 0;
7477       DBG("@@ ->IN 0x%x 0x%x %s md=%s dt=%s",
7478              ev->win, ev->event_win,
7479              ct,
7480              modes[ev->mode],
7481              details[ev->detail]);
7482    }
7483 #endif
7484    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7485    if (ev->event_win == bd->win)
7486      {
7487         e_focus_event_mouse_in(bd);
7488      }
7489 #if 0
7490    if ((ev->win != bd->win) &&
7491        (ev->win != bd->event_win) &&
7492        (ev->event_win != bd->win) &&
7493        (ev->event_win != bd->event_win))
7494      return ECORE_CALLBACK_PASS_ON;
7495 #else
7496    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7497 #endif
7498    bd->mouse.current.mx = ev->root.x;
7499    bd->mouse.current.my = ev->root.y;
7500    if (!bd->bg_evas_in)
7501      {
7502         evas_event_feed_mouse_in(bd->bg_evas, ev->time, NULL);
7503         bd->bg_evas_in = EINA_TRUE;
7504      }
7505    return ECORE_CALLBACK_PASS_ON;
7506 }
7507
7508 static Eina_Bool
7509 _e_border_cb_mouse_out(void    *data,
7510                        int type __UNUSED__,
7511                        void    *event)
7512 {
7513    Ecore_X_Event_Mouse_Out *ev;
7514    E_Border *bd;
7515
7516    ev = event;
7517    bd = data;
7518 #ifdef INOUTDEBUG_MOUSE
7519    {
7520       time_t t;
7521       char *ct;
7522
7523       const char *modes[] = {
7524          "MODE_NORMAL",
7525          "MODE_WHILE_GRABBED",
7526          "MODE_GRAB",
7527          "MODE_UNGRAB"
7528       };
7529       const char *details[] = {
7530          "DETAIL_ANCESTOR",
7531          "DETAIL_VIRTUAL",
7532          "DETAIL_INFERIOR",
7533          "DETAIL_NON_LINEAR",
7534          "DETAIL_NON_LINEAR_VIRTUAL",
7535          "DETAIL_POINTER",
7536          "DETAIL_POINTER_ROOT",
7537          "DETAIL_DETAIL_NONE"
7538       };
7539       t = time(NULL);
7540       ct = ctime(&t);
7541       ct[strlen(ct) - 1] = 0;
7542       DBG("@@ <-OUT 0x%x 0x%x %s md=%s dt=%s",
7543              ev->win, ev->event_win,
7544              ct,
7545              modes[ev->mode],
7546              details[ev->detail]);
7547    }
7548 #endif
7549    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7550    if (ev->event_win == bd->win)
7551      {
7552         if (bd->fullscreen)
7553           return ECORE_CALLBACK_PASS_ON;
7554         if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
7555             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7556           return ECORE_CALLBACK_PASS_ON;
7557         if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7558           return ECORE_CALLBACK_PASS_ON;
7559         if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
7560             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7561           return ECORE_CALLBACK_PASS_ON;
7562         e_focus_event_mouse_out(bd);
7563      }
7564 #if 0
7565    if ((ev->win != bd->win) &&
7566        (ev->win != bd->event_win) &&
7567        (ev->event_win != bd->win) &&
7568        (ev->event_win != bd->event_win))
7569      return ECORE_CALLBACK_PASS_ON;
7570 #else
7571    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7572 #endif
7573    bd->mouse.current.mx = ev->root.x;
7574    bd->mouse.current.my = ev->root.y;
7575    if (bd->bg_evas_in)
7576      {
7577         if (!((evas_event_down_count_get(bd->bg_evas) > 0) &&
7578               (!((ev->mode == ECORE_X_EVENT_MODE_GRAB) &&
7579                  (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)))))
7580           {
7581              if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7582                evas_event_feed_mouse_cancel(bd->bg_evas, ev->time, NULL);
7583              evas_event_feed_mouse_out(bd->bg_evas, ev->time, NULL);
7584              bd->bg_evas_in = EINA_FALSE;
7585           }
7586      }
7587    return ECORE_CALLBACK_PASS_ON;
7588 }
7589
7590 static Eina_Bool
7591 _e_border_cb_mouse_wheel(void    *data,
7592                          int type __UNUSED__,
7593                          void    *event)
7594 {
7595    Ecore_Event_Mouse_Wheel *ev;
7596    E_Border *bd;
7597
7598    ev = event;
7599    bd = data;
7600    if ((ev->event_window == bd->win) ||
7601        (ev->event_window == bd->event_win))
7602      {
7603         bd->mouse.current.mx = ev->root.x;
7604         bd->mouse.current.my = ev->root.y;
7605         if (!bd->cur_mouse_action)
7606           e_bindings_wheel_event_handle(E_BINDING_CONTEXT_WINDOW,
7607                                         E_OBJECT(bd), ev);
7608      }
7609    evas_event_feed_mouse_wheel(bd->bg_evas, ev->direction, ev->z, ev->timestamp, NULL);
7610    return ECORE_CALLBACK_PASS_ON;
7611 }
7612
7613 static Eina_Bool
7614 _e_border_cb_mouse_down(void    *data,
7615                         int type __UNUSED__,
7616                         void    *event)
7617 {
7618    Ecore_Event_Mouse_Button *ev;
7619    E_Border *bd;
7620
7621    ev = event;
7622    bd = data;
7623    if ((ev->event_window == bd->win) ||
7624        (ev->event_window == bd->event_win))
7625      {
7626         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7627           {
7628              bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7629              bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7630              bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7631              bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7632              bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7633              bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7634           }
7635         else
7636           {
7637              bd->moveinfo.down.x = bd->x + bd->fx.x;
7638              bd->moveinfo.down.y = bd->y + bd->fx.y;
7639              bd->moveinfo.down.w = bd->w;
7640              bd->moveinfo.down.h = bd->h;
7641           }
7642         bd->mouse.current.mx = ev->root.x;
7643         bd->mouse.current.my = ev->root.y;
7644         if (!bd->cur_mouse_action)
7645           {
7646              bd->cur_mouse_action =
7647                e_bindings_mouse_down_event_handle(E_BINDING_CONTEXT_WINDOW,
7648                                                   E_OBJECT(bd), ev);
7649              if (bd->cur_mouse_action)
7650                {
7651                   if ((!bd->cur_mouse_action->func.end_mouse) &&
7652                       (!bd->cur_mouse_action->func.end))
7653                     bd->cur_mouse_action = NULL;
7654                   if (bd->cur_mouse_action)
7655                     e_object_ref(E_OBJECT(bd->cur_mouse_action));
7656                }
7657           }
7658         e_focus_event_mouse_down(bd);
7659      }
7660    if (ev->window != ev->event_window)
7661      {
7662         return 1;
7663      }
7664    if ((ev->window != bd->event_win) && (ev->event_window != bd->win))
7665      {
7666         return 1;
7667      }
7668    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7669      {
7670         bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7671         bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7672         bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7673         bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7674         bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7675         bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7676      }
7677    else
7678      {
7679         bd->moveinfo.down.x = bd->x + bd->fx.x;
7680         bd->moveinfo.down.y = bd->y + bd->fx.y;
7681         bd->moveinfo.down.w = bd->w;
7682         bd->moveinfo.down.h = bd->h;
7683      }
7684    bd->mouse.current.mx = ev->root.x;
7685    bd->mouse.current.my = ev->root.y;
7686 /*
7687    if (bd->moving)
7688      {
7689      }
7690    else if (bd->resize_mode != RESIZE_NONE)
7691      {
7692      }
7693    else
7694  */
7695    {
7696       Evas_Button_Flags flags = EVAS_BUTTON_NONE;
7697
7698       if (ev->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
7699       if (ev->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
7700       evas_event_feed_mouse_down(bd->bg_evas, ev->buttons, flags, ev->timestamp, NULL);
7701    }
7702    return ECORE_CALLBACK_PASS_ON;
7703 }
7704
7705 static Eina_Bool
7706 _e_border_cb_mouse_up(void    *data,
7707                       int type __UNUSED__,
7708                       void    *event)
7709 {
7710    Ecore_Event_Mouse_Button *ev;
7711    E_Border *bd;
7712
7713    ev = event;
7714    bd = data;
7715    if ((ev->event_window == bd->win) ||
7716        (ev->event_window == bd->event_win))
7717      {
7718         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7719           {
7720              bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7721              bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7722              bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7723              bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7724           }
7725         bd->mouse.current.mx = ev->root.x;
7726         bd->mouse.current.my = ev->root.y;
7727         /* also we dont pass the same params that went in - then again that */
7728         /* should be ok as we are just ending the action if it has an end */
7729         if (bd->cur_mouse_action)
7730           {
7731              if (bd->cur_mouse_action->func.end_mouse)
7732                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", ev);
7733              else if (bd->cur_mouse_action->func.end)
7734                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
7735              e_object_unref(E_OBJECT(bd->cur_mouse_action));
7736              bd->cur_mouse_action = NULL;
7737           }
7738         else
7739           {
7740              if (!e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd), ev))
7741                e_focus_event_mouse_up(bd);
7742           }
7743      }
7744    if (ev->window != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7745    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7746      {
7747         bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7748         bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7749         bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7750         bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7751      }
7752    bd->mouse.current.mx = ev->root.x;
7753    bd->mouse.current.my = ev->root.y;
7754
7755    bd->drag.start = 0;
7756
7757    evas_event_feed_mouse_up(bd->bg_evas, ev->buttons, EVAS_BUTTON_NONE, ev->timestamp, NULL);
7758    return ECORE_CALLBACK_PASS_ON;
7759 }
7760
7761 static void
7762 _e_border_stay_within_container(E_Border *bd, int x, int y, int *new_x, int *new_y)
7763 {
7764 #ifdef _F_BORDER_CLIP_TO_ZONE_
7765    int new_x_max, new_y_max;
7766    int new_x_min, new_y_min;
7767    int margin_x, margin_y;
7768
7769    margin_x = bd->w - 100;
7770    margin_y = bd->h - 100;
7771
7772    new_x_max = bd->zone->x + bd->zone->w - bd->w + margin_x;
7773    new_x_min = bd->zone->x - margin_x;
7774    new_y_max = bd->zone->y + bd->zone->h - bd->h + margin_y;
7775    new_y_min = bd->zone->y - margin_y;
7776
7777    if (x >= new_x_max)      *new_x = new_x_max;
7778    else if (x <= new_x_min) *new_x = new_x_min;
7779
7780    if (y >= new_y_max)      *new_y = new_y_max;
7781    else if (y <= new_y_min) *new_y = new_y_min;
7782 #endif
7783 }
7784
7785 static Eina_Bool
7786 _e_border_cb_mouse_move(void    *data,
7787                         int type __UNUSED__,
7788                         void    *event)
7789 {
7790    Ecore_Event_Mouse_Move *ev;
7791    E_Border *bd;
7792
7793    ev = event;
7794    bd = data;
7795    if ((ev->window != bd->event_win) &&
7796        (ev->event_window != bd->win)) return ECORE_CALLBACK_PASS_ON;
7797    bd->mouse.current.mx = ev->root.x;
7798    bd->mouse.current.my = ev->root.y;
7799    if (bd->moving)
7800      {
7801         int x, y, new_x, new_y;
7802         int new_w, new_h;
7803         Eina_List *skiplist = NULL;
7804 #if 0
7805         // FIXME: remove? sync what for when only moving?
7806         if ((ecore_loop_time_get() - bd->client.netwm.sync.time) > 0.5)
7807           bd->client.netwm.sync.wait = 0;
7808         if ((bd->client.netwm.sync.request) &&
7809             (bd->client.netwm.sync.alarm) &&
7810             (bd->client.netwm.sync.wait > 1)) return ECORE_CALLBACK_PASS_ON;
7811 #endif
7812         if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
7813           {
7814              x = bd->mouse.last_down[bd->moveinfo.down.button - 1].x +
7815                (bd->mouse.current.mx - bd->moveinfo.down.mx);
7816              y = bd->mouse.last_down[bd->moveinfo.down.button - 1].y +
7817                (bd->mouse.current.my - bd->moveinfo.down.my);
7818           }
7819         else
7820           {
7821              x = bd->moveinfo.down.x +
7822                (bd->mouse.current.mx - bd->moveinfo.down.mx);
7823              y = bd->moveinfo.down.y +
7824                (bd->mouse.current.my - bd->moveinfo.down.my);
7825           }
7826         new_x = x;
7827         new_y = y;
7828
7829 #ifdef _F_USE_RESIST_MAGNETIC_EFFECT_
7830         skiplist = eina_list_append(skiplist, bd);
7831         e_resist_container_border_position(bd->zone->container, skiplist,
7832                                            bd->x, bd->y, bd->w, bd->h,
7833                                            x, y, bd->w, bd->h,
7834                                            &new_x, &new_y, &new_w, &new_h);
7835         eina_list_free(skiplist);
7836
7837         _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
7838 #else
7839         /* if (e_config->window_out_of_vscreen_limits_partly) */
7840         if (1)
7841           _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
7842         else
7843           {
7844              skiplist = eina_list_append(skiplist, bd);
7845              e_resist_container_border_position(bd->zone->container, skiplist,
7846                                                 bd->x, bd->y, bd->w, bd->h,
7847                                                 x, y, bd->w, bd->h,
7848                                                 &new_x, &new_y, &new_w, &new_h);
7849              eina_list_free(skiplist);
7850           }
7851 #endif
7852         bd->shelf_fix.x = 0;
7853         bd->shelf_fix.y = 0;
7854         bd->shelf_fix.modified = 0;
7855         e_border_move(bd, new_x, new_y);
7856         e_zone_flip_coords_handle(bd->zone, ev->root.x, ev->root.y);
7857      }
7858    else if (bd->resize_mode != RESIZE_NONE)
7859      {
7860         if ((bd->client.netwm.sync.request) &&
7861             (bd->client.netwm.sync.alarm))
7862           {
7863              if ((ecore_loop_time_get() - bd->client.netwm.sync.send_time) > 0.5)
7864                {
7865                   E_Border_Pending_Move_Resize *pnd;
7866
7867                   if (bd->pending_move_resize)
7868                     {
7869                        bd->changes.pos = 1;
7870                        bd->changes.size = 1;
7871                        bd->changed = 1;
7872                        _e_border_client_move_resize_send(bd);
7873                     }
7874                   EINA_LIST_FREE(bd->pending_move_resize, pnd)
7875                     E_FREE(pnd);
7876
7877                   bd->client.netwm.sync.wait = 0;
7878                }
7879              /* sync.wait is incremented when resize_handle sends
7880               * sync-request and decremented by sync-alarm cb. so
7881               * we resize here either on initial resize, timeout or
7882               * when no new resize-request was added by sync-alarm cb.
7883               */
7884              if (!bd->client.netwm.sync.wait)
7885                _e_border_resize_handle(bd);
7886           }
7887         else
7888           _e_border_resize_handle(bd);
7889      }
7890    else
7891      {
7892         if (bd->drag.start)
7893           {
7894              if ((bd->drag.x == -1) && (bd->drag.y == -1))
7895                {
7896                   bd->drag.x = ev->root.x;
7897                   bd->drag.y = ev->root.y;
7898                }
7899              else
7900                {
7901                   int dx, dy;
7902
7903                   dx = bd->drag.x - ev->root.x;
7904                   dy = bd->drag.y - ev->root.y;
7905                   if (((dx * dx) + (dy * dy)) >
7906                       (e_config->drag_resist * e_config->drag_resist))
7907                     {
7908      /* start drag! */
7909                         if (bd->icon_object)
7910                           {
7911                              Evas_Object *o = NULL;
7912                              Evas_Coord x, y, w, h;
7913                              const char *drag_types[] = { "enlightenment/border" };
7914
7915                              e_object_ref(E_OBJECT(bd));
7916                              evas_object_geometry_get(bd->icon_object,
7917                                                       &x, &y, &w, &h);
7918                              drag_border = e_drag_new(bd->zone->container,
7919                                                       bd->x + bd->fx.x + x,
7920                                                       bd->y + bd->fx.y + y,
7921                                                       drag_types, 1, bd, -1,
7922                                                       NULL,
7923                                                       _e_border_cb_drag_finished);
7924                              o = e_border_icon_add(bd, drag_border->evas);
7925                              if (!o)
7926                                {
7927      /* FIXME: fallback icon for drag */
7928                                    o = evas_object_rectangle_add(drag_border->evas);
7929                                    evas_object_color_set(o, 255, 255, 255, 255);
7930                                }
7931                              e_drag_object_set(drag_border, o);
7932
7933                              e_drag_resize(drag_border, w, h);
7934                              e_drag_start(drag_border, bd->drag.x, bd->drag.y);
7935                           }
7936                         bd->drag.start = 0;
7937                     }
7938                }
7939           }
7940         evas_event_feed_mouse_move(bd->bg_evas, ev->x, ev->y, ev->timestamp, NULL);
7941      }
7942    return ECORE_CALLBACK_PASS_ON;
7943 }
7944
7945 static Eina_Bool
7946 _e_border_cb_grab_replay(void *data __UNUSED__,
7947                          int        type,
7948                          void      *event)
7949 {
7950    Ecore_Event_Mouse_Button *ev;
7951
7952    if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
7953    ev = event;
7954    if ((e_config->pass_click_on)
7955        || (e_config->always_click_to_raise) // this works even if not on click-to-focus
7956        || (e_config->always_click_to_focus) // this works even if not on click-to-focus
7957       )
7958      {
7959         E_Border *bd;
7960
7961         bd = e_border_find_by_window(ev->event_window);
7962         if (bd)
7963           {
7964              if (bd->cur_mouse_action)
7965                return ECORE_CALLBACK_DONE;
7966              if (ev->event_window == bd->win)
7967                {
7968                   if (!e_bindings_mouse_down_find(E_BINDING_CONTEXT_WINDOW,
7969                                                   E_OBJECT(bd), ev, NULL))
7970                     return ECORE_CALLBACK_PASS_ON;
7971                }
7972           }
7973      }
7974    return ECORE_CALLBACK_DONE;
7975 }
7976
7977 static void
7978 _e_border_cb_drag_finished(E_Drag     *drag,
7979                            int dropped __UNUSED__)
7980 {
7981    E_Border *bd;
7982
7983    bd = drag->data;
7984    e_object_unref(E_OBJECT(bd));
7985    drag_border = NULL;
7986 }
7987
7988 #ifdef _F_USE_DESK_WINDOW_PROFILE_
7989 static Eina_Bool
7990 _e_border_cb_desk_window_profile_change(void *data  __UNUSED__,
7991                                         int ev_type __UNUSED__,
7992                                         void       *ev)
7993 {
7994    E_Event_Desk_Window_Profile_Change *e;
7995    Eina_List *l;
7996    E_Border *bd;
7997
7998    e = ev;
7999    EINA_LIST_FOREACH(borders, l, bd)
8000      {
8001         if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
8002           {
8003              bd->client.e.fetch.profile_list = 1;
8004              bd->changed = 1;
8005           }
8006      }
8007    return ECORE_CALLBACK_PASS_ON;
8008 }
8009 #endif
8010
8011 #ifdef _F_ZONE_WINDOW_ROTATION_
8012 static Eina_Bool
8013 _e_border_cb_zone_rotation_change_begin(void *data  __UNUSED__,
8014                                         int ev_type __UNUSED__,
8015                                         void       *ev)
8016 {
8017    E_Event_Zone_Rotation_Change_Begin *e = ev;
8018
8019    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8020    if ((!e) || (!e->zone)) return ECORE_CALLBACK_PASS_ON;
8021
8022    if (!_e_border_rotation_zone_set(e->zone))
8023      {
8024         /* there is no border which supports window manager rotation */
8025         e_zone_rotation_update_cancel(e->zone);
8026      }
8027    return ECORE_CALLBACK_PASS_ON;
8028 }
8029
8030 static void
8031 _e_border_cb_rotation_sync_job(void *data)
8032 {
8033    E_Zone *zone = data;
8034    Eina_List *l;
8035    E_Border_Rotation_Info *info = NULL;
8036
8037    ELB(ELBT_ROT, "DO ROTATION SYNC_JOB", zone->id);
8038
8039    if (rot.list)
8040      {
8041         EINA_LIST_FOREACH(rot.list, l, info)
8042            _e_border_hook_call(E_BORDER_HOOK_ROTATION_LIST_ADD, info->bd);
8043         if (!rot.wait_prepare_done)
8044           {
8045              _e_border_rotation_change_request(zone);
8046           }
8047      }
8048
8049    // clear job
8050    if (rot.sync_job)
8051      {
8052         ELB(ELBT_ROT, "DEL SYNC_JOB", zone->id);
8053         ecore_job_del(rot.sync_job);
8054         rot.sync_job = NULL;
8055      }
8056 }
8057
8058 static void
8059 _e_border_cb_rotation_async_job(void *data)
8060 {
8061    E_Zone *zone = data;
8062
8063    if (rot.list) goto end;
8064
8065    ELB(ELBT_ROT, "FLUSH ASYNC LIST TO ROT_CHANGE_REQ", zone->id);
8066
8067    if (!rot.wait_prepare_done)
8068      {
8069         _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8070         rot.async_list = NULL;
8071      }
8072
8073 end:
8074    // clear async job
8075    if (rot.async_job)
8076      {
8077         ELB(ELBT_ROT, "DEL ASYNC_JOB", zone->id);
8078         ecore_job_del(rot.async_job);
8079         rot.async_job = NULL;
8080      }
8081 }
8082
8083 static Eina_Bool
8084 _e_border_rotation_change_prepare_timeout(void *data)
8085 {
8086    E_Zone *zone = data;
8087    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8088
8089    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE_PREPARE", 0);
8090
8091    if ((zone) && (rot.wait_prepare_done))
8092      {
8093         if (rot.list)
8094           {
8095              _e_border_rotation_change_request(zone);
8096              if (rot.prepare_timer)
8097                ecore_timer_del(rot.prepare_timer);
8098              rot.prepare_timer = NULL;
8099              rot.wait_prepare_done = EINA_FALSE;
8100           }
8101      }
8102    return ECORE_CALLBACK_CANCEL;
8103 }
8104
8105 static void
8106 _e_border_rotation_change_request(E_Zone *zone)
8107 {
8108    if (!e_config->wm_win_rotation) return;
8109    if (!rot.list) return;
8110    if (eina_list_count(rot.list) <= 0) return;
8111    if (zone->rot.block_count) return;
8112
8113    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8114    rot.prepare_timer = NULL;
8115    rot.wait_prepare_done = EINA_FALSE;
8116
8117    _e_border_rotation_list_flush(rot.list, EINA_FALSE);
8118
8119    if (rot.done_timer)
8120      ecore_timer_del(rot.done_timer);
8121    ELB(ELBT_ROT, "ADD TIMEOUT ROT_DONE", zone->id);
8122    rot.done_timer = ecore_timer_add(5.0f,
8123                                     _e_border_rotation_change_done_timeout,
8124                                     NULL);
8125 }
8126
8127 static void
8128 _e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush)
8129 {
8130    Eina_List *l;
8131    E_Border_Rotation_Info *info =NULL;
8132    int x, y, w, h;
8133
8134    EINA_LIST_FOREACH (list, l, info)
8135      {
8136         if (!info->bd) continue;
8137         if ((info->bd->client.e.state.rot.wait_for_done) &&
8138             (info->bd->client.e.state.rot.wait_done_ang == info->ang)) continue;
8139
8140         _e_border_event_border_rotation_change_begin_send(info->bd);
8141
8142         /* resize border */
8143         info->win_resize = _e_border_rotation_pre_resize(info->bd, info->ang, &x, &y, &w, &h);
8144         info->bd->client.e.state.rot.pending_change_request = info->win_resize;
8145
8146         info->x = x; info->y = y;
8147         info->w = w; info->h = h;
8148
8149         ELBF(ELBT_ROT, 1, info->bd->client.win,
8150              "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
8151              info->ang, info->win_resize, info->w, info->h);
8152
8153         ecore_x_e_window_rotation_change_prepare_send
8154            (info->bd->client.win, info->ang,
8155             info->win_resize, info->w, info->h);
8156
8157         if (!info->bd->client.e.state.rot.pending_change_request)
8158           {
8159              ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
8160              ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
8161                                                            info->ang);
8162              info->bd->client.e.state.rot.wait_for_done = 1;
8163              info->bd->client.e.state.rot.wait_done_ang = info->ang;
8164           }
8165      }
8166
8167    if (flush)
8168      {
8169         EINA_LIST_FREE(list, info)
8170            E_FREE(info);
8171      }
8172 }
8173
8174 EAPI void
8175 e_border_rotation_list_clear(E_Zone *zone, Eina_Bool send_request)
8176 {
8177    E_Border_Rotation_Info *info = NULL;
8178
8179    if (send_request) _e_border_rotation_change_request(zone);
8180    else
8181      {
8182         EINA_LIST_FREE(rot.list, info)
8183            E_FREE(info);
8184         rot.list = NULL;
8185      }
8186 }
8187
8188 static void
8189 _e_border_rotation_list_remove(E_Border *bd)
8190 {
8191    Eina_List *l = NULL;
8192    E_Border_Rotation_Info *info = NULL;
8193    E_Event_Border_Rotation_Change_End *ev = NULL;
8194    Eina_Bool found = EINA_FALSE;
8195
8196    if (!e_config->wm_win_rotation) return;
8197
8198    EINA_LIST_FOREACH(rot.list, l, info)
8199      {
8200         if (info->bd == bd)
8201           {
8202              rot.list = eina_list_remove(rot.list, info);
8203              E_FREE(info);
8204              found = EINA_TRUE;
8205           }
8206      }
8207
8208    if (bd->client.e.state.rot.wait_for_done)
8209      {
8210         bd->client.e.state.rot.wait_for_done = 0;
8211
8212         /* if we make the border event in the _e_border_free function,
8213          * then we may meet a crash problem, only work this at least e_border_hide.
8214          */
8215         if (!e_object_is_del(E_OBJECT(bd)))
8216           {
8217              ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
8218              if (ev)
8219                {
8220                   ev->border = bd;
8221                   e_object_ref(E_OBJECT(bd));
8222                   ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_END,
8223                                   ev,
8224                                   _e_border_event_border_rotation_change_end_free,
8225                                   NULL);
8226                }
8227           }
8228
8229         if ((found) &&
8230             (eina_list_count(rot.list) == 0))
8231           {
8232              _e_border_rotation_change_done();
8233           }
8234      }
8235 }
8236
8237 static Eina_Bool
8238 _e_border_rotation_change_done_timeout(void *data __UNUSED__)
8239 {
8240    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8241    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE", 0);
8242    _e_border_rotation_change_done();
8243    return ECORE_CALLBACK_CANCEL;
8244 }
8245
8246 static void
8247 _e_border_rotation_change_done(void)
8248 {
8249    E_Manager *m = NULL;
8250    E_Border_Rotation_Info *info = NULL;
8251
8252    if (!e_config->wm_win_rotation) return;
8253
8254    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8255    rot.prepare_timer = NULL;
8256
8257    rot.wait_prepare_done = EINA_FALSE;
8258
8259    if (rot.done_timer) ecore_timer_del(rot.done_timer);
8260    rot.done_timer = NULL;
8261
8262    EINA_LIST_FREE(rot.list, info)
8263      {
8264         if (info->bd)
8265           {
8266              ELB(ELBT_ROT, "TIMEOUT ROT_DONE", info->bd->client.win);
8267              if (info->bd->client.e.state.rot.pending_show)
8268                {
8269                   ELB(ELBT_ROT, "SHOW PEND(TIMEOUT)", info->bd->client.win);
8270                   e_border_show(info->bd);
8271 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
8272                   if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
8273                     _e_border_check_stack(info->bd);
8274 #endif
8275                   info->bd->client.e.state.rot.pending_show = 0;
8276                }
8277              info->bd->client.e.state.rot.wait_for_done = 0;
8278           }
8279         E_FREE(info);
8280      }
8281
8282    _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8283
8284    rot.list = NULL;
8285    rot.async_list = NULL;
8286
8287    m = e_manager_current_get();
8288    e_manager_comp_screen_unlock(m);
8289    e_zone_rotation_update_done(e_util_zone_current_get(m));
8290 }
8291
8292 static int
8293 _prev_angle_get(Ecore_X_Window win)
8294 {
8295    int ret, count = 0, ang = -1;
8296    unsigned char* data = NULL;
8297
8298    ret = ecore_x_window_prop_property_get
8299       (win, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
8300       ECORE_X_ATOM_CARDINAL, 32, &data, &count);
8301
8302    if ((ret) && (data) && (count))
8303      ang = ((int *)data)[0];
8304    if (data) free(data);
8305    return ang;
8306 }
8307
8308 /* get proper rotation value using preferred rotation and list of available rotations */
8309 static int
8310 _e_border_rotation_get(E_Border *bd,
8311                        int       base_ang)
8312 {
8313    int ang = -1;
8314    int current_ang = bd->client.e.state.rot.curr;
8315    unsigned int i;
8316    Eina_Bool found = EINA_FALSE;
8317    Eina_Bool found_curr_ang = EINA_FALSE;
8318
8319    if (!e_config->wm_win_rotation) return ang;
8320    if (!bd->client.e.state.rot.app_set) return ang;
8321
8322    if (bd->client.e.state.rot.preferred_rot != -1)
8323      {
8324         ang = bd->client.e.state.rot.preferred_rot;
8325         ELBF(ELBT_ROT, 0, bd->client.win, "ang:%d base_ang:%d", ang, base_ang);
8326      }
8327    else if ((bd->client.e.state.rot.available_rots) &&
8328             (bd->client.e.state.rot.count))
8329      {
8330         for (i = 0; i < bd->client.e.state.rot.count; i++)
8331           {
8332              if (bd->client.e.state.rot.available_rots[i] == base_ang)
8333                {
8334                   ang = base_ang;
8335                   found = EINA_TRUE;
8336                   break;
8337                }
8338              if (bd->client.e.state.rot.available_rots[i] == current_ang)
8339                found_curr_ang = EINA_TRUE;
8340           }
8341
8342         /* do nothing. this window wants to maintain current state.
8343          * for example, window's available_rots: 0, 90, 270,
8344          * current zone rotation request: 180. the WM does nothing
8345          * for this window.
8346          */
8347         if (!found)
8348           {
8349              if ((bd->client.e.state.rot.curr != -1) && (found_curr_ang))
8350                ang = bd->client.e.state.rot.curr;
8351              else
8352                ang = bd->client.e.state.rot.available_rots[0];
8353           }
8354      }
8355    else
8356      {
8357         /* In this case, border doesn't have a list of
8358          * available rotations, thus WM should request
8359          * rotation with '0' degree to the application.
8360          */
8361         ang = 0;
8362      }
8363
8364    return ang;
8365 }
8366
8367 static int
8368 _e_border_rotation_angle_get(E_Border *bd)
8369 {
8370    E_Zone *zone = bd->zone;
8371    int will_ang = 0;
8372    int _ang = 0;
8373    int ret = -1;
8374
8375    if (!e_config->wm_win_rotation) return ret;
8376    if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) return ret;
8377
8378    ELB(ELBT_ROT, "CHECK ROT", bd->client.win);
8379
8380    // the window with "ECORE_X_WINDOW_TYPE_NORMAL" type
8381    // should follow the state of rotation of zone.
8382    if ((bd->parent) &&
8383        (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL))
8384      will_ang = bd->parent->client.e.state.rot.curr;
8385    else will_ang = zone->rot.curr;
8386
8387    if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
8388      {
8389         ELBF(ELBT_ROT, 1, bd->client.win,
8390              "%s->parent:0x%08x (support:%d app_set:%d ang:%d)",
8391              (rot.vkbd == bd) ? "vkbd" : "prediction",
8392              bd->parent ? bd->parent->client.win : 0,
8393              bd->parent ? bd->parent->client.e.state.rot.support : -1,
8394              bd->parent ? bd->parent->client.e.state.rot.app_set : -1,
8395              bd->parent ? bd->parent->client.e.state.rot.curr : -1);
8396
8397         if (bd->parent)
8398           {
8399              will_ang = bd->parent->client.e.state.rot.curr;
8400              if ((!bd->parent->client.e.state.rot.support) &&
8401                  (!bd->parent->client.e.state.rot.app_set))
8402                {
8403                   will_ang = 0;
8404                }
8405           }
8406      }
8407
8408    if ((!bd->client.e.state.rot.app_set) &&
8409        (!bd->client.e.state.rot.support))
8410      {
8411         /* hack for magnifier and keyboard popup */
8412         if ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER) ||
8413             (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP))
8414           {
8415              ELB(ELBT_BD, "MAG", bd->client.win);
8416              will_ang = 0;
8417              if ((rot.vkbd) && (rot.vkbd->visible))
8418                will_ang = rot.vkbd->client.e.state.rot.curr;
8419           }
8420      }
8421
8422    if (bd->client.e.state.rot.app_set)
8423      {
8424         /* utility type window should be rotated according to
8425          * rotation of the transient_for window.
8426          */
8427         if ((bd->parent) &&
8428             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
8429           {
8430              will_ang = bd->parent->client.e.state.rot.curr;
8431              if ((!bd->parent->client.e.state.rot.support) &&
8432                  (!bd->parent->client.e.state.rot.app_set))
8433                {
8434                   /* if transient_for window doesn't support rotation feature,
8435                    * then this window should't be rotated.
8436                    * TODO: need to check whether window supports '0' degree or not.
8437                    */
8438                   will_ang = 0;
8439                   ELBF(ELBT_ROT, 0, bd->client.win,
8440                        "GET ROT ang:%d Transient_For:0x%08x Not support rot",
8441                        will_ang, bd->parent->client.win);
8442                }
8443              else
8444                {
8445                   will_ang = _e_border_rotation_get(bd->parent, will_ang);
8446                   ELBF(ELBT_ROT, 0, bd->client.win,
8447                        "GET ROT ang:%d Transient_For:0x%08x",
8448                        will_ang, bd->parent->client.win);
8449                }
8450           }
8451         else
8452           {
8453              will_ang = _e_border_rotation_get(bd, will_ang);
8454              ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d",
8455                   will_ang, bd->parent ? bd->parent->client.win : 0,
8456                   bd->client.netwm.type);
8457           }
8458      }
8459
8460    if (bd->new_client)
8461      {
8462         _ang = _prev_angle_get(bd->client.win);
8463         if (_ang != -1)
8464           bd->client.e.state.rot.curr = _ang;
8465         ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang);
8466      }
8467
8468    if (bd->client.e.state.rot.curr != will_ang)
8469      ret = will_ang;
8470
8471    return ret;
8472 }
8473
8474
8475 static Eina_Bool
8476 _e_border_rotation_zone_set(E_Zone *zone)
8477 {
8478    E_Border_List *l = NULL;
8479    E_Border *bd = NULL;
8480    Eina_Bool ret = EINA_FALSE;
8481
8482    if (!e_config->wm_win_rotation) return EINA_FALSE;
8483
8484    l = e_container_border_list_last(zone->container);
8485    if (!l) return ret;
8486
8487    /* step 1. make the list needs to be rotated. */
8488    while ((bd = e_container_border_list_prev(l)))
8489      {
8490         if (!bd) continue;
8491
8492         // if this window has parent and window type isn't "ECORE_X_WINDOW_TYPE_NORMAL",
8493         // it will be rotated when parent do rotate itself.
8494         // so skip here.
8495         if ((bd->parent) &&
8496             (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL)) continue;
8497
8498         // default type is "E_BORDER_ROTATION_TYPE_NORMAL",
8499         // but it can be changed to "E_BORDER_ROTATION_TYPE_DEPENDENT" by illume according to its policy.
8500         // if it's not normal type window, will be rotated by illume.
8501         // so skip here.
8502         if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue;
8503
8504         if ((!bd->visible) ||
8505             (!E_INTERSECTS(bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h,
8506                            bd->x, bd->y, bd->w, bd->h))) continue;
8507
8508         if (_e_border_rotatable_check(bd, zone->rot.curr))
8509           {
8510              ELBF(ELBT_ROT, 0, bd->client.win, "ROT_SET(main) curr:%d != TOBE:%d",
8511                   bd->client.e.state.rot.curr, zone->rot.curr);
8512
8513              ret = e_border_rotation_set(bd, zone->rot.curr);
8514           }
8515      }
8516    if (l) e_container_border_list_free(l);
8517
8518    return ret;
8519 }
8520
8521 static Eina_Bool
8522 _e_border_rotation_set_internal(E_Border *bd, int rotation, Eina_Bool *pending)
8523 {
8524    E_Zone *zone = bd->zone;
8525    E_Border_Rotation_Info *info = NULL;
8526    Eina_List *list, *l;
8527    E_Border *child;
8528
8529    if (rotation < 0) return EINA_FALSE;
8530    if (pending) *pending = EINA_FALSE;
8531
8532    /* step 1. check if rotation */
8533    if (!_e_border_rotatable_check(bd, rotation)) return EINA_FALSE;
8534
8535    /* step 2. add to async/sync list */
8536    if ((!zone->rot.block_count) &&
8537        ((!bd->visible) ||
8538         (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))))
8539      {
8540         // send rotation change request later.
8541         // and no need to wait message of rotation done.
8542
8543         // async list add
8544         info = E_NEW(E_Border_Rotation_Info, 1);
8545         if (!info) return EINA_FALSE;
8546         ELB(ELBT_ROT, "ADD ASYNC LIST", 0);
8547         info->bd = bd;
8548         info->ang = rotation;
8549         rot.async_list = eina_list_append(rot.async_list, info);
8550
8551         // add job for sending event.
8552         if (!rot.async_job)
8553           {
8554              ELB(ELBT_ROT, "ADD ASYNC_JOB", bd->client.win);
8555              rot.async_job = ecore_job_add(_e_border_cb_rotation_async_job, zone);
8556           }
8557      }
8558    else
8559      {
8560         // sync list add
8561         info = E_NEW(E_Border_Rotation_Info, 1);
8562         if (!info) return EINA_FALSE;
8563         ELB(ELBT_ROT, "ADD SYNC LIST", 0);
8564         info->bd = bd;
8565         info->ang = rotation;
8566         rot.list = eina_list_append(rot.list, info);
8567
8568         // add job for sending event.
8569         if (!rot.sync_job)
8570           {
8571              ELB(ELBT_ROT, "ADD SYNC_JOB", bd->client.win);
8572              rot.sync_job = ecore_job_add(_e_border_cb_rotation_sync_job, zone);
8573           }
8574
8575         // if there is windows over 2 that has to be rotated or is existed window needs resizing,
8576         // lock the screen.
8577         // but, DO NOT lock the screen when rotation block state.
8578         if ((!zone->rot.block_count) &&
8579             ((eina_list_count(rot.list) == 2)))
8580           e_manager_comp_screen_lock(e_manager_current_get());
8581      }
8582
8583    if (pending) *pending = EINA_TRUE;
8584
8585    /* step 3. search rotatable window in this window's child */
8586    list = _e_border_sub_borders_new(bd);
8587    EINA_LIST_FOREACH(list, l, child)
8588      {
8589         // the window which type is "ECORE_X_WINDOW_TYPE_NORMAL" will be rotated itself.
8590         // it shouldn't be rotated by rotation state of parent window.
8591         if (child->client.netwm.type == ECORE_X_WINDOW_TYPE_NORMAL) continue;
8592         if (_e_border_rotatable_check(child, rotation))
8593           {
8594              ELBF(ELBT_ROT, 0, child->client.win, "ROT_SET(child) curr:%d != TOBE:%d",
8595                   bd->client.e.state.rot.curr, rotation);
8596              e_border_rotation_set(child, rotation);
8597           }
8598      }
8599
8600    /* step 4. if there is vkbd window, send message to prepare rotation */
8601    if (_e_border_is_vkbd(bd))
8602      {
8603         ELB(ELBT_ROT, "PENDING ROT_REQ UNTIL GET PREP_DONE", rot.vkbd_ctrl_win);
8604         if (rot.prepare_timer)
8605           ecore_timer_del(rot.prepare_timer);
8606         rot.prepare_timer = NULL;
8607
8608         if (rot.done_timer)
8609           ecore_timer_del(rot.done_timer);
8610         rot.done_timer = NULL;
8611
8612         ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win);
8613         ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8614                                                       zone->rot.curr,
8615                                                       EINA_FALSE, 1, 1);
8616         rot.prepare_timer = ecore_timer_add(4.0f,
8617                                             _e_border_rotation_change_prepare_timeout,
8618                                             NULL);
8619
8620         rot.wait_prepare_done = EINA_TRUE;
8621      }
8622
8623    bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8624    bd->client.e.state.rot.curr = rotation;
8625
8626    return EINA_TRUE;
8627 }
8628
8629 // check if border is rotatable in ang.
8630 static Eina_Bool
8631 _e_border_rotatable_check(E_Border *bd, int ang)
8632 {
8633    Eina_Bool ret = EINA_FALSE;
8634
8635    if (!bd) return ret;
8636    if (ang < 0) return ret;
8637    if ((!bd->client.e.state.rot.support) && (!bd->client.e.state.rot.app_set)) return ret;
8638    if (e_object_is_del(E_OBJECT(bd))) return ret;
8639
8640    // same with current angle of window, then false return.
8641    if (ang == bd->client.e.state.rot.curr) return ret;
8642
8643    /* basically WM allows only fullscreen window to rotate */
8644    if (bd->client.e.state.rot.preferred_rot == -1)
8645      {
8646         unsigned int i;
8647
8648         if (bd->client.e.state.rot.app_set)
8649           {
8650              if (bd->client.e.state.rot.available_rots &&
8651                  bd->client.e.state.rot.count)
8652                {
8653                   Eina_Bool found = EINA_FALSE;
8654                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8655                     {
8656                        if (bd->client.e.state.rot.available_rots[i] == ang)
8657                          {
8658                             found = EINA_TRUE;
8659                          }
8660                     }
8661                   if (found) ret = EINA_TRUE;
8662                }
8663           }
8664         else
8665           {
8666              ELB(ELBT_ROT, "DO ROT", 0);
8667              ret = EINA_TRUE;
8668           }
8669      }
8670    // if it has preferred rotation angle,
8671    // it will be rotated at border's evaluation time.
8672    // so skip it.
8673    else if (bd->client.e.state.rot.preferred_rot == ang) ret = EINA_TRUE;
8674
8675    return ret;
8676 }
8677
8678 /* check whether virtual keyboard is visible on the zone */
8679 static Eina_Bool
8680 _e_border_is_vkbd(E_Border *bd)
8681 {
8682    if (!e_config->wm_win_rotation) return EINA_FALSE;
8683
8684    if ((rot.vkbd_ctrl_win) &&
8685        (rot.vkbd == bd) &&
8686        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8687        (rot.vkbd->zone == bd->zone) &&
8688        (E_INTERSECTS(bd->zone->x, bd->zone->y,
8689                      bd->zone->w, bd->zone->h,
8690                      rot.vkbd->x, rot.vkbd->y,
8691                      rot.vkbd->w, rot.vkbd->h)))
8692      {
8693         return EINA_TRUE;
8694      }
8695    return EINA_FALSE;
8696 }
8697
8698 static Eina_Bool
8699 _e_border_rotation_change_floating_pos(E_Border *bd, int *x, int *y)
8700 {
8701    int new_x, new_y;
8702    int min_title_width=96;
8703
8704    if (!bd) return EINA_FALSE;
8705    if (!x || !y) return EINA_FALSE;
8706
8707    new_x = bd->x;
8708    new_y = bd->y;
8709
8710    // Portrait -> Landscape,  x= pre_x*2, y=pre_y/2
8711    // Landscape -> Portrait,  x= pre_x/2, y=pre_y*2
8712    // guaranteeing the minimum size of titlebar shown, min_title_width
8713    // so user can initiate drag&drop action after rotation changed.
8714    if (bd->client.e.state.rot.curr == 0)
8715      {
8716         if (bd->client.e.state.rot.prev == 90)
8717           {
8718              new_x = (bd->zone->h - bd->h - bd->y) / 2;
8719              new_y = 2 * bd->x;
8720           }
8721         else if (bd->client.e.state.rot.prev == 270)
8722           {
8723              new_x = bd->y / 2;
8724              new_y = (bd->zone->w - bd->w - bd->x) * 2;
8725           }
8726         else if (bd->client.e.state.rot.prev == 180)
8727           {
8728              new_x = bd->zone->w - bd->x - bd->w;
8729              new_y = bd->zone->h - bd->y - bd->h;
8730           }
8731
8732         if(new_x + bd->w < min_title_width)
8733           {
8734              new_x = min_title_width - bd->w;
8735           }
8736         else if(new_x > bd->zone->w - min_title_width)
8737           {
8738              new_x = bd->zone->w - min_title_width;
8739           }
8740      }
8741    else if (bd->client.e.state.rot.curr == 90)
8742      {
8743         if (bd->client.e.state.rot.prev == 0)
8744           {
8745              new_x = bd->y / 2;
8746              new_y = bd->zone->h - (2 * bd->x) - bd->w;
8747           }
8748         else if (bd->client.e.state.rot.prev == 270)
8749           {
8750              new_x = bd->zone->w - bd->x - bd->w;
8751              new_y = bd->zone->h - bd->y - bd->h;
8752           }
8753         else if (bd->client.e.state.rot.prev == 180)
8754           {
8755              new_x = (bd->zone->h - bd->y - bd->h) / 2;
8756              new_y = bd->zone->h - (2 * (bd->zone->w - bd->x - bd->w)) - bd->w;
8757           }
8758
8759         if(new_y > bd->zone->h - min_title_width)
8760           {
8761              new_y = bd->zone->h - min_title_width;
8762           }
8763         else if(new_y < min_title_width - bd->w)
8764           {
8765              new_y = min_title_width - bd->w;
8766           }
8767      }
8768    else if (bd->client.e.state.rot.curr == 270)
8769      {
8770         if (bd->client.e.state.rot.prev == 0)
8771           {
8772              new_x = bd->zone->w - bd->h - (bd->y / 2);
8773              new_y = bd->x * 2;
8774           }
8775         else if (bd->client.e.state.rot.prev == 90)
8776           {
8777              new_x = bd->zone->w - bd->x - bd->w;
8778              new_y = bd->zone->h - bd->y - bd->h;
8779           }
8780         else if (bd->client.e.state.rot.prev == 180)
8781           {
8782              new_x = bd->zone->w - bd->x - bd->w;
8783              new_y = bd->zone->h - bd->y - bd->h;
8784
8785              new_x = bd->zone->w - bd->h - ((bd->zone->h - bd->y - bd->h) / 2);
8786              new_y = (bd->zone->w - bd->x - bd->w) * 2;
8787           }
8788
8789         if(new_y >  bd->zone->h - min_title_width)
8790           {
8791              new_y = bd->zone->h - min_title_width;
8792           }
8793         else if( new_y + bd->w < min_title_width)
8794           {
8795              new_y = min_title_width - bd->w ;
8796           }
8797      }
8798    else if (bd->client.e.state.rot.curr == 180)
8799      {
8800         if (bd->client.e.state.rot.prev == 0)
8801           {
8802              new_x = bd->zone->w - bd->x - bd->w;
8803              new_y = bd->zone->h - bd->y - bd->h;
8804           }
8805         else if (bd->client.e.state.rot.prev == 90)
8806           {
8807              new_x = bd->zone->w - ((bd->zone->h - bd->h - bd->y) / 2) - bd->h;
8808              new_y = bd->zone->h - (2 * bd->x) - bd->w;
8809           }
8810         else if (bd->client.e.state.rot.prev == 270)
8811           {
8812              new_x = bd->zone->w - (bd->y / 2) - bd->h;
8813              new_y = bd->zone->h - ((bd->zone->w - bd->w - bd->x) * 2) - bd->w;
8814           }
8815
8816         if(new_x + bd->w < min_title_width)
8817           {
8818              new_x = min_title_width - bd->w;
8819           }
8820         else if(new_x > bd->zone->w - min_title_width)
8821           {
8822              new_x = bd->zone->w - min_title_width;
8823           }
8824      }
8825
8826    ELBF(ELBT_ROT, 0, bd->client.win,
8827         "Floating Mode. ANGLE (%d->%d), POS (%d,%d) -> (%d,%d)",
8828         bd->client.e.state.rot.prev, bd->client.e.state.rot.curr,
8829         bd->x, bd->y, new_x, new_y);
8830
8831    if ((new_x == *x) &&
8832        (new_y == *y))
8833      {
8834         return EINA_FALSE;
8835      }
8836
8837    *x = new_x;
8838    *y = new_y;
8839
8840    return EINA_TRUE;
8841 }
8842
8843 #define SIZE_EQUAL_TO_ZONE(a, z) \
8844    ((((a)->w) == ((z)->w)) &&    \
8845     (((a)->h) == ((z)->h)))
8846 static Eina_Bool
8847 _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h)
8848 {
8849    E_Zone *zone = bd->zone;
8850    int rot_dif;
8851    int _x, _y, _w, _h;
8852    Eina_Bool move = EINA_FALSE;
8853    Eina_Bool hint = EINA_FALSE;
8854    Eina_Bool resize = EINA_FALSE;
8855
8856    if (x) *x = bd->x;
8857    if (y) *y = bd->y;
8858    if (w) *w = bd->w;
8859    if (h) *h = bd->h;
8860
8861    if (SIZE_EQUAL_TO_ZONE(bd, zone)) return resize;
8862
8863    ELB(ELBT_ROT, "SIZE DIFF WITH ZONE", 0);
8864    ELBF(ELBT_ROT, 0, bd->client.win, "ORIGIN_SIZE name:%s (%d,%d) %dx%d",
8865         bd->client.icccm.name, bd->x, bd->y, bd->w, bd->h);
8866
8867    hint = _e_border_rotation_geom_get(bd, bd->zone, rotation,
8868                                       &_x, &_y, &_w, &_h, &move);
8869    if (hint)
8870      {
8871         _e_border_move_resize_internal(bd, _x, _y, _w, _h, EINA_TRUE, move);
8872         resize = EINA_TRUE;
8873         ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
8874              bd->client.icccm.name, _x, _y, _w, _h);
8875      }
8876    else
8877      {
8878         _x = bd->x; _y = bd->y;
8879         _w = bd->w; _h = bd->h;
8880
8881         if (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)
8882           move = _e_border_rotation_change_floating_pos(bd, &_x, &_y);
8883         else
8884           move = EINA_FALSE;
8885
8886         rot_dif = bd->client.e.state.rot.prev - rotation;
8887         if (rot_dif < 0) rot_dif = -rot_dif;
8888         if (rot_dif != 180)
8889           {
8890              if (w != h)
8891                {
8892                   _w = bd->h;
8893                   _h = bd->w;
8894                   resize = EINA_TRUE;
8895
8896                   _e_border_move_resize_internal(bd, _x, _y, _w, _h,
8897                                                  EINA_TRUE, EINA_TRUE);
8898                   ELBF(ELBT_ROT, 0, bd->client.win, "MANUAL_RESIZE name:%s (%d,%d) %dx%d",
8899                        bd->client.icccm.name, _x, _y, _w, _h);
8900
8901                }
8902           }
8903
8904         if (!resize && move)
8905           _e_border_move_internal(bd, _x, _y, EINA_TRUE);
8906      }
8907
8908    if (resize)
8909      {
8910         if (x) *x = _x;
8911         if (y) *y = _y;
8912         if (w) *w = _w;
8913         if (h) *h = _h;
8914      }
8915
8916    return resize;
8917 }
8918
8919 static Eina_Bool
8920 _e_border_cb_window_configure(void *data    __UNUSED__,
8921                               int   ev_type __UNUSED__,
8922                               void         *ev)
8923 {
8924    Ecore_X_Event_Window_Configure *e = ev;
8925    E_Border_Rotation_Info *info = NULL;
8926    Eina_List *l;
8927    Eina_Bool found = EINA_FALSE;
8928
8929    if (!e) return ECORE_CALLBACK_PASS_ON;
8930    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8931
8932    E_Border *bd = e_border_find_by_client_window(e->win);
8933    if (!bd) return ECORE_CALLBACK_PASS_ON;
8934
8935    if (bd->client.e.state.rot.pending_change_request)
8936      {
8937         if ((e->w == bd->w) && (e->h == bd->h))
8938           {
8939              ELB(ELBT_BD, "GET CONFIGURE_NOTI (ROTATION)", bd->client.win);
8940              bd->client.e.state.rot.pending_change_request = 0;
8941
8942              if ((bd->client.e.state.rot.wait_for_done) &&
8943                  (bd->client.e.state.rot.wait_done_ang == bd->client.e.state.rot.curr)) goto end;
8944
8945              // if this window is rotation dependent window and zone is blocked to rotate,
8946              // then skip here, request will be sent after cancel block.
8947              if ((bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_DEPENDENT) &&
8948                  (bd->zone->rot.block_count)) goto end;
8949
8950              EINA_LIST_FOREACH(rot.list, l, info)
8951                 if (info->bd == bd) found = EINA_TRUE;
8952              // send request message if it's async rotation window,
8953              // even if wait prepare done.
8954              if ((found) && (rot.wait_prepare_done)) goto end;
8955
8956              ELBF(ELBT_ROT, 0, bd->client.win,
8957                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
8958                   bd->client.e.state.rot.curr,
8959                   bd->w, bd->h);
8960              ecore_x_e_window_rotation_change_request_send(bd->client.win,
8961                                                            bd->client.e.state.rot.curr);
8962              bd->client.e.state.rot.wait_for_done = 1;
8963              bd->client.e.state.rot.wait_done_ang = bd->client.e.state.rot.curr;
8964           }
8965      }
8966
8967 end:
8968    return ECORE_CALLBACK_PASS_ON;
8969 }
8970
8971 static Eina_Bool
8972 _e_border_rotation_geom_get(E_Border  *bd,
8973                             E_Zone    *zone,
8974                             int        ang,
8975                             int       *x,
8976                             int       *y,
8977                             int       *w,
8978                             int       *h,
8979                             Eina_Bool *move)
8980 {
8981    if (!e_config->wm_win_rotation) return EINA_FALSE;
8982
8983    Eina_Bool res = EINA_FALSE;
8984    Eina_Bool _move = EINA_TRUE;
8985    int _x = bd->x;
8986    int _y = bd->y;
8987    int _w = bd->w;
8988    int _h = bd->h;
8989
8990    if (x) *x = bd->x;
8991    if (y) *y = bd->y;
8992    if (w) *w = bd->w;
8993    if (h) *h = bd->h;
8994    if (move) *move = EINA_TRUE;
8995
8996    if (bd->client.e.state.rot.geom_hint)
8997      {
8998         switch (ang)
8999           {
9000            case   0:
9001               _w = bd->client.e.state.rot.geom[0].w;
9002               _h = bd->client.e.state.rot.geom[0].h;
9003               if (_w == 0) _w = bd->w;
9004               if (_h == 0) _h = bd->h;
9005               _x = 0; _y = zone->h - _h;
9006               break;
9007            case  90:
9008               _w = bd->client.e.state.rot.geom[1].w;
9009               _h = bd->client.e.state.rot.geom[1].h;
9010               if (_w == 0) _w = bd->w;
9011               if (_h == 0) _h = bd->h;
9012               _x = zone->w - _w; _y = 0;
9013               break;
9014            case 180:
9015               _w = bd->client.e.state.rot.geom[2].w;
9016               _h = bd->client.e.state.rot.geom[2].h;
9017               if (_w == 0) _w = bd->w;
9018               if (_h == 0) _h = bd->h;
9019               _x = 0; _y = 0;
9020               break;
9021            case 270:
9022               _w = bd->client.e.state.rot.geom[3].w;
9023               _h = bd->client.e.state.rot.geom[3].h;
9024               if (_w == 0) _w = bd->w;
9025               if (_h == 0) _h = bd->h;
9026               _x = 0; _y = 0;
9027               break;
9028           }
9029
9030         if (x) *x = _x;
9031         if (y) *y = _y;
9032         if (w) *w = _w;
9033         if (h) *h = _h;
9034
9035         if (!((rot.vkbd) && (rot.vkbd == bd)))
9036           {
9037              if (x) *x = bd->x;
9038              if (y) *y = bd->y;
9039              if (move) *move = EINA_FALSE;
9040           }
9041
9042         res = EINA_TRUE;
9043      }
9044
9045    if (res)
9046      {
9047         _x = 0; _y = 0; _w = 0; _h = 0;
9048         if (x) _x = *x;
9049         if (y) _y = *y;
9050         if (w) _w = *w;
9051         if (h) _h = *h;
9052         if (move) _move = *move;
9053
9054         ELBF(ELBT_ROT, 1, bd->client.win,
9055              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
9056              ang, _x, _y, _w, _h, _move);
9057      }
9058
9059    return res;
9060 }
9061 #endif
9062
9063 static Eina_Bool
9064 _e_border_post_move_resize_job(void *data)
9065 {
9066    E_Border *bd;
9067
9068    bd = (E_Border *)data;
9069    if (bd->post_move)
9070      {
9071         E_Border *tmp;
9072         Eina_List *l;
9073
9074         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
9075           ecore_x_window_move(tmp->win,
9076                               bd->x +
9077                               bd->client_inset.l +
9078                               bd->fx.x +
9079                               tmp->client.e.state.video_position.x,
9080                               bd->y +
9081                               bd->client_inset.t +
9082                               bd->fx.y +
9083                               tmp->client.e.state.video_position.y);
9084      }
9085    if (bd->client.e.state.video)
9086      {
9087         E_Border *parent;
9088
9089         parent = bd->client.e.state.video_parent_border;
9090         ecore_x_window_move(bd->win,
9091                             parent->x +
9092                             parent->client_inset.l +
9093                             parent->fx.x +
9094                             bd->client.e.state.video_position.x,
9095                             parent->y +
9096                             parent->client_inset.t +
9097                             parent->fx.y +
9098                             bd->client.e.state.video_position.y);
9099      }
9100    else if ((bd->post_move) && (bd->post_resize))
9101      {
9102         ecore_x_window_move_resize(bd->win,
9103                                    bd->x + bd->fx.x,
9104                                    bd->y + bd->fx.y,
9105                                    bd->w, bd->h);
9106      }
9107    else if (bd->post_move)
9108      {
9109         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
9110      }
9111    else if (bd->post_resize)
9112      {
9113         ecore_x_window_resize(bd->win, bd->w, bd->h);
9114      }
9115
9116    if (bd->client.e.state.video)
9117      {
9118         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
9119                 bd->win,
9120                 bd->client.e.state.video_parent_border->x +
9121                 bd->client.e.state.video_parent_border->client_inset.l +
9122                 bd->client.e.state.video_parent_border->fx.x +
9123                 bd->client.e.state.video_position.x,
9124                 bd->client.e.state.video_parent_border->y +
9125                 bd->client.e.state.video_parent_border->client_inset.t +
9126                 bd->client.e.state.video_parent_border->fx.y +
9127                 bd->client.e.state.video_position.y,
9128                 bd->w, bd->h);
9129      }
9130
9131    if (bd->post_show)
9132      {
9133         if (bd->visible)
9134           {
9135              bd->post_job = NULL;
9136              _e_border_show(bd);
9137           }
9138      }
9139    bd->post_show = 0;
9140    bd->post_move = 0;
9141    bd->post_resize = 0;
9142    bd->post_job = NULL;
9143    return ECORE_CALLBACK_CANCEL;
9144 }
9145
9146 static void
9147 _e_border_container_layout_hook(E_Container *con)
9148 {
9149    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
9150 }
9151
9152 static void
9153 _e_border_eval0(E_Border *bd)
9154 {
9155    int change_urgent = 0;
9156    int rem_change = 0;
9157 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9158    Eina_Bool need_desk_set = EINA_FALSE;
9159 #endif
9160 #ifdef _F_ZONE_WINDOW_ROTATION_
9161    Eina_Bool need_rotation_set = EINA_FALSE;
9162
9163    if ((e_config->wm_win_rotation) &&
9164        (bd->client.icccm.fetch.transient_for))
9165      {
9166         if (((rot.vkbd) && (rot.vkbd == bd)) ||
9167             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
9168           {
9169              need_rotation_set = EINA_TRUE;
9170              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
9171           }
9172      }
9173 #endif
9174
9175    if (e_object_is_del(E_OBJECT(bd)))
9176      {
9177         CRI("_e_border_eval(%p) with deleted border!\n", bd);
9178         bd->changed = 0;
9179         return;
9180      }
9181
9182    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
9183
9184    bd->changes.border = 0;
9185
9186    /* fetch any info queued to be fetched */
9187    if (bd->client.netwm.fetch.state)
9188      {
9189         e_hints_window_state_get(bd);
9190         bd->client.netwm.fetch.state = 0;
9191         rem_change = 1;
9192      }
9193    if (bd->client.icccm.fetch.client_leader)
9194      {
9195         /* TODO: What do to if the client leader isn't mapped yet? */
9196         E_Border *bd_leader = NULL;
9197
9198         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
9199         if (bd->client.icccm.client_leader)
9200           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
9201         if (bd->leader)
9202           {
9203              if (bd->leader != bd_leader)
9204                {
9205                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
9206                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
9207                   bd->leader = NULL;
9208                }
9209              else
9210                bd_leader = NULL;
9211           }
9212         /* If this border is the leader of the group, don't register itself */
9213         if ((bd_leader) && (bd_leader != bd))
9214           {
9215              bd_leader->group = eina_list_append(bd_leader->group, bd);
9216              bd->leader = bd_leader;
9217              /* Only set the window modal to the leader it there is no parent */
9218              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
9219                  ((!bd->parent) || (bd->parent->modal != bd)))
9220                {
9221                   bd->leader->modal = bd;
9222                   if (bd->leader->focused)
9223                     e_border_focus_set(bd, 1, 1);
9224                   else
9225                     {
9226                        Eina_List *l;
9227                        E_Border *child;
9228
9229                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9230                          {
9231                             if ((child != bd) && (child->focused))
9232                               e_border_focus_set(bd, 1, 1);
9233                          }
9234                     }
9235                }
9236           }
9237         bd->client.icccm.fetch.client_leader = 0;
9238         rem_change = 1;
9239      }
9240    if (bd->client.icccm.fetch.title)
9241      {
9242         char *title = ecore_x_icccm_title_get(bd->client.win);
9243         eina_stringshare_replace(&bd->client.icccm.title, title);
9244         if (title) free(title);
9245
9246         if (bd->bg_object)
9247           edje_object_part_text_set(bd->bg_object, "e.text.title",
9248                                     bd->client.icccm.title);
9249         bd->client.icccm.fetch.title = 0;
9250         rem_change = 1;
9251      }
9252    if (bd->client.netwm.fetch.name)
9253      {
9254         char *name;
9255         ecore_x_netwm_name_get(bd->client.win, &name);
9256         eina_stringshare_replace(&bd->client.netwm.name, name);
9257         if (name) free(name);
9258
9259         if (bd->bg_object)
9260           edje_object_part_text_set(bd->bg_object, "e.text.title",
9261                                     bd->client.netwm.name);
9262         bd->client.netwm.fetch.name = 0;
9263         rem_change = 1;
9264      }
9265    if (bd->client.icccm.fetch.name_class)
9266      {
9267         const char *pname, *pclass;
9268         char *nname, *nclass;
9269
9270         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
9271         pname = bd->client.icccm.name;
9272         pclass = bd->client.icccm.class;
9273         bd->client.icccm.name = eina_stringshare_add(nname);
9274         bd->client.icccm.class = eina_stringshare_add(nclass);
9275         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
9276           e_bindings_mapping_change_enable(EINA_FALSE);
9277 #ifdef _F_ZONE_WINDOW_ROTATION_
9278         if (e_config->wm_win_rotation)
9279           {
9280              if ((bd->client.icccm.name) && (bd->client.icccm.class))
9281                {
9282                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
9283                       (!strcmp(bd->client.icccm.class, "ISF")))
9284                     {
9285                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
9286                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
9287                        rot.vkbd = bd;
9288                     }
9289                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
9290                            (!strcmp(bd->client.icccm.class, "ISF")))
9291                     {
9292                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
9293                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
9294                        rot.vkbd_prediction = bd;
9295                     }
9296                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
9297                            (!strcmp(bd->client.icccm.class, "ISF")))
9298                     {
9299                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
9300                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
9301                     }
9302                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
9303                            (!strcmp(bd->client.icccm.class, "ISF")))
9304                     {
9305                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
9306                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
9307                     }
9308                }
9309           }
9310 #endif
9311         if (nname) free(nname);
9312         if (nclass) free(nclass);
9313
9314         if (!((bd->client.icccm.name == pname) &&
9315               (bd->client.icccm.class == pclass)))
9316           bd->changes.icon = 1;
9317
9318         if (pname) eina_stringshare_del(pname);
9319         if (pclass) eina_stringshare_del(pclass);
9320         bd->client.icccm.fetch.name_class = 0;
9321         bd->changes.icon = 1;
9322         rem_change = 1;
9323      }
9324    if (bd->client.icccm.fetch.state)
9325      {
9326         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
9327         bd->client.icccm.fetch.state = 0;
9328         rem_change = 1;
9329      }
9330    if (bd->client.e.fetch.state)
9331      {
9332         e_hints_window_e_state_get(bd);
9333         bd->client.e.fetch.state = 0;
9334         rem_change = 1;
9335      }
9336 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9337    if (bd->client.e.fetch.profile_list)
9338      {
9339         const char **profiles = NULL;
9340         const char *str;
9341         int num = 0, i;
9342
9343         if (bd->client.e.state.profile)
9344           eina_stringshare_del(bd->client.e.state.profile);
9345         EINA_LIST_FREE(bd->client.e.state.profiles, str)
9346           {
9347              if (str) eina_stringshare_del(str);
9348           }
9349         bd->client.e.state.profile = NULL;
9350         bd->client.e.state.profiles = NULL;
9351         bd->client.e.state.profile_list = 0;
9352
9353         if (ecore_x_e_window_profile_list_get(bd->client.win,
9354                                               &profiles, &num))
9355           {
9356              bd->client.e.state.profile_list = 1;
9357              for (i = 0; i < num; i++)
9358                {
9359                   str = eina_stringshare_add(profiles[i]);
9360                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
9361                }
9362
9363              /* We should set desk to contain given border after creating E_BORDER_ADD event.
9364               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
9365               */
9366              need_desk_set = EINA_TRUE;
9367           }
9368         else
9369           {
9370              if (strcmp(bd->desk->window_profile,
9371                         e_config->desktop_default_window_profile) != 0)
9372                {
9373                   ecore_x_e_window_profile_set(bd->client.win,
9374                                                bd->desk->window_profile);
9375                }
9376           }
9377
9378         if (profiles)
9379           {
9380              for (i = 0; i < num; i++)
9381                 if (profiles[i]) free(profiles[i]);
9382              free(profiles);
9383           }
9384
9385         bd->client.e.fetch.profile_list = 0;
9386      }
9387 #endif
9388 #ifdef _F_ZONE_WINDOW_ROTATION_
9389    if ((e_config->wm_win_rotation) &&
9390        (bd->client.e.fetch.rot.support))
9391      {
9392         int ret = 0;
9393         unsigned int support = 0;
9394
9395         ret = ecore_x_window_prop_card32_get
9396           (bd->client.win,
9397           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
9398           &support, 1);
9399
9400         bd->client.e.state.rot.support = 0;
9401         if ((ret == 1) && (support == 1))
9402           bd->client.e.state.rot.support = 1;
9403
9404         if (bd->client.e.state.rot.support)
9405           need_rotation_set = EINA_TRUE;
9406
9407         bd->client.e.fetch.rot.support = 0;
9408      }
9409    if ((e_config->wm_win_rotation) &&
9410        (bd->client.e.fetch.rot.geom_hint))
9411      {
9412         Eina_Rectangle r[4];
9413         int i, x, y, w, h;
9414         bd->client.e.state.rot.geom_hint = 0;
9415         for (i = 0; i < 4; i++)
9416           {
9417              r[i].x = bd->client.e.state.rot.geom[i].x;
9418              r[i].y = bd->client.e.state.rot.geom[i].y;
9419              r[i].w = bd->client.e.state.rot.geom[i].w;
9420              r[i].h = bd->client.e.state.rot.geom[i].h;
9421
9422              bd->client.e.state.rot.geom[i].x = 0;
9423              bd->client.e.state.rot.geom[i].y = 0;
9424              bd->client.e.state.rot.geom[i].w = 0;
9425              bd->client.e.state.rot.geom[i].h = 0;
9426           }
9427
9428         for (i = 0; i < 4; i++)
9429           {
9430              x = 0; y = 0; w = 0; h = 0;
9431              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
9432                {
9433                   bd->client.e.state.rot.geom_hint = 1;
9434                   bd->client.e.state.rot.geom[i].x = x;
9435                   bd->client.e.state.rot.geom[i].y = y;
9436                   bd->client.e.state.rot.geom[i].w = w;
9437                   bd->client.e.state.rot.geom[i].h = h;
9438
9439                   if (!((r[i].x == x) && (r[i].y == y) &&
9440                         (r[i].w == w) && (r[i].h == h)))
9441                     {
9442                        need_rotation_set = EINA_TRUE;
9443                     }
9444                }
9445           }
9446         bd->client.e.fetch.rot.geom_hint = 0;
9447      }
9448    if ((e_config->wm_win_rotation) &&
9449        (bd->client.e.fetch.rot.app_set))
9450      {
9451         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
9452         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
9453         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
9454
9455         if (_prev_app_set != bd->client.e.state.rot.app_set)
9456           need_rotation_set = EINA_TRUE;
9457
9458         bd->client.e.fetch.rot.app_set = 0;
9459      }
9460    if ((e_config->wm_win_rotation) &&
9461        (bd->client.e.fetch.rot.preferred_rot))
9462      {
9463         int r = 0, _prev_preferred_rot;
9464         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
9465         bd->client.e.state.rot.preferred_rot = -1;
9466         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
9467           {
9468              bd->client.e.state.rot.preferred_rot = r;
9469              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
9470           }
9471         else
9472           {
9473              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
9474           }
9475
9476         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
9477           need_rotation_set = EINA_TRUE;
9478
9479         bd->client.e.fetch.rot.preferred_rot = 0;
9480      }
9481    if ((e_config->wm_win_rotation) &&
9482        (bd->client.e.fetch.rot.available_rots))
9483      {
9484         Eina_Bool res, diff = EINA_FALSE;
9485         int *rots = NULL;
9486         unsigned int count = 0, i = 0;
9487         int _prev_rots[4] = { -1, };
9488
9489         if (bd->client.e.state.rot.available_rots)
9490           {
9491              memcpy(_prev_rots,
9492                     bd->client.e.state.rot.available_rots,
9493                     (sizeof(int) * bd->client.e.state.rot.count));
9494
9495              E_FREE(bd->client.e.state.rot.available_rots);
9496           }
9497
9498         bd->client.e.state.rot.count = 0;
9499
9500         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
9501                                                                 &rots, &count);
9502         if ((res) && (count > 0) && (rots))
9503           {
9504              bd->client.e.state.rot.available_rots = rots;
9505              bd->client.e.state.rot.count = count;
9506
9507              for (i = 0; i < count; i++)
9508                {
9509                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
9510                   if ((!diff) && (_prev_rots[i] != rots[i]))
9511                     {
9512                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
9513                             count, i, _prev_rots[i], rots[i]);
9514                        diff = EINA_TRUE;
9515                     }
9516                }
9517           }
9518         else
9519           {
9520              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9521              diff = EINA_TRUE;
9522           }
9523
9524         if (diff) need_rotation_set = EINA_TRUE;
9525         bd->client.e.fetch.rot.available_rots = 0;
9526      }
9527 #endif
9528    if (bd->client.netwm.fetch.type)
9529      {
9530         e_hints_window_type_get(bd);
9531         if ((!bd->lock_border) || (!bd->client.border.name))
9532           bd->client.border.changed = 1;
9533
9534         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9535           {
9536              if (!bd->client.netwm.state.skip_pager)
9537                {
9538                   bd->client.netwm.state.skip_pager = 1;
9539                   bd->client.netwm.update.state = 1;
9540                }
9541              if (!bd->client.netwm.state.skip_taskbar)
9542                {
9543                   bd->client.netwm.state.skip_taskbar = 1;
9544                   bd->client.netwm.update.state = 1;
9545                }
9546           }
9547         bd->client.netwm.fetch.type = 0;
9548      }
9549    if (bd->client.icccm.fetch.machine)
9550      {
9551         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9552
9553         if ((!machine) && (bd->client.icccm.client_leader))
9554           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9555
9556         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9557         if (machine) free(machine);
9558
9559         bd->client.icccm.fetch.machine = 0;
9560         rem_change = 1;
9561      }
9562    if (bd->client.icccm.fetch.command)
9563      {
9564         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9565           {
9566              int i;
9567
9568              for (i = 0; i < bd->client.icccm.command.argc; i++)
9569                free(bd->client.icccm.command.argv[i]);
9570              free(bd->client.icccm.command.argv);
9571           }
9572         bd->client.icccm.command.argc = 0;
9573         bd->client.icccm.command.argv = NULL;
9574         ecore_x_icccm_command_get(bd->client.win,
9575                                   &(bd->client.icccm.command.argc),
9576                                   &(bd->client.icccm.command.argv));
9577         if ((bd->client.icccm.client_leader) &&
9578             (!bd->client.icccm.command.argv))
9579           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9580                                     &(bd->client.icccm.command.argc),
9581                                     &(bd->client.icccm.command.argv));
9582         bd->client.icccm.fetch.command = 0;
9583         rem_change = 1;
9584      }
9585    if (bd->client.icccm.fetch.hints)
9586      {
9587         Eina_Bool accepts_focus, is_urgent;
9588
9589         accepts_focus = EINA_TRUE;
9590         is_urgent = EINA_FALSE;
9591         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9592         if (ecore_x_icccm_hints_get(bd->client.win,
9593                                     &accepts_focus,
9594                                     &bd->client.icccm.initial_state,
9595                                     &bd->client.icccm.icon_pixmap,
9596                                     &bd->client.icccm.icon_mask,
9597                                     &bd->client.icccm.icon_window,
9598                                     &bd->client.icccm.window_group,
9599                                     &is_urgent))
9600           {
9601              bd->client.icccm.accepts_focus = accepts_focus;
9602              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9603                change_urgent = 1;
9604              bd->client.icccm.urgent = is_urgent;
9605
9606              /* If this is a new window, set the state as requested. */
9607              if ((bd->new_client) &&
9608                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9609                {
9610                   e_border_iconify(bd);
9611                   e_border_hide(bd, 1);
9612                }
9613           }
9614         bd->client.icccm.fetch.hints = 0;
9615         rem_change = 1;
9616      }
9617    if (bd->client.icccm.fetch.size_pos_hints)
9618      {
9619         Eina_Bool request_pos;
9620
9621         request_pos = EINA_FALSE;
9622         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9623                                              &request_pos,
9624                                              &bd->client.icccm.gravity,
9625                                              &bd->client.icccm.min_w,
9626                                              &bd->client.icccm.min_h,
9627                                              &bd->client.icccm.max_w,
9628                                              &bd->client.icccm.max_h,
9629                                              &bd->client.icccm.base_w,
9630                                              &bd->client.icccm.base_h,
9631                                              &bd->client.icccm.step_w,
9632                                              &bd->client.icccm.step_h,
9633                                              &bd->client.icccm.min_aspect,
9634                                              &bd->client.icccm.max_aspect))
9635           {
9636              bd->client.icccm.request_pos = request_pos;
9637           }
9638         else
9639           {
9640           }
9641         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9642         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9643         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9644         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9645         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9646         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9647         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9648         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9649         // if doing a resize, fix it up
9650         if (bd->resize_mode != RESIZE_NONE)
9651           {
9652              int x, y, w, h, new_w, new_h;
9653
9654              x = bd->x;
9655              y = bd->y;
9656              w = bd->w;
9657              h = bd->h;
9658              new_w = w;
9659              new_h = h;
9660              e_border_resize_limit(bd, &new_w, &new_h);
9661              if ((bd->resize_mode == RESIZE_TL) ||
9662                  (bd->resize_mode == RESIZE_L) ||
9663                  (bd->resize_mode == RESIZE_BL))
9664                x += (w - new_w);
9665              if ((bd->resize_mode == RESIZE_TL) ||
9666                  (bd->resize_mode == RESIZE_T) ||
9667                  (bd->resize_mode == RESIZE_TR))
9668                y += (h - new_h);
9669              e_border_move_resize(bd, x, y, new_w, new_h);
9670           }
9671         bd->client.icccm.fetch.size_pos_hints = 0;
9672         rem_change = 1;
9673      }
9674    if (bd->client.icccm.fetch.protocol)
9675      {
9676         int i, num;
9677         Ecore_X_WM_Protocol *proto;
9678
9679         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9680         if (proto)
9681           {
9682              for (i = 0; i < num; i++)
9683                {
9684                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9685                     bd->client.icccm.delete_request = 1;
9686                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9687                     bd->client.icccm.take_focus = 1;
9688                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9689                     bd->client.netwm.ping = 1;
9690                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9691                     {
9692                        bd->client.netwm.sync.request = 1;
9693                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9694                                                            &bd->client.netwm.sync.counter))
9695                          bd->client.netwm.sync.request = 0;
9696                     }
9697                }
9698              free(proto);
9699           }
9700         if (bd->client.netwm.ping)
9701           e_border_ping(bd);
9702         else
9703           {
9704              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9705              bd->ping_poller = NULL;
9706           }
9707         bd->client.icccm.fetch.protocol = 0;
9708      }
9709    if (bd->client.icccm.fetch.transient_for)
9710      {
9711         /* TODO: What do to if the transient for isn't mapped yet? */
9712         E_Border *bd_parent = NULL;
9713 #ifdef _F_DEICONIFY_APPROVE_
9714         Eina_Bool change_parent = EINA_FALSE;
9715 #endif
9716
9717         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9718         if (bd->client.icccm.transient_for)
9719           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9720         /* If we already have a parent, remove it */
9721         if (bd->parent)
9722           {
9723              if (bd_parent != bd->parent)
9724                {
9725                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9726                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9727                   bd->parent = NULL;
9728                }
9729              else
9730                bd_parent = NULL;
9731           }
9732         if ((bd_parent) && (bd_parent != bd) &&
9733             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9734           {
9735              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9736              bd->parent = bd_parent;
9737 #ifdef _F_DEICONIFY_APPROVE_
9738              change_parent = EINA_TRUE;
9739 #endif
9740           }
9741         if (bd->parent)
9742           {
9743              e_border_layer_set(bd, bd->parent->layer);
9744              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9745                {
9746                   Ecore_X_Window_Attributes attr;
9747                   bd->parent->modal = bd;
9748                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9749                   bd->parent->saved.event_mask = attr.event_mask.mine;
9750                   bd->parent->lock_close = 1;
9751                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9752                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9753                }
9754
9755              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9756                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9757                bd->take_focus = 1;
9758           }
9759
9760 #ifdef _F_DEICONIFY_APPROVE_
9761         if (change_parent)
9762           {
9763              bd->client.e.state.deiconify_approve.render_done = 0;
9764
9765              E_Border *ancestor_bd;
9766              ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
9767              if ((ancestor_bd) &&
9768                  (!e_object_is_del(E_OBJECT(ancestor_bd))))
9769                {
9770                   ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
9771                   bd->client.e.state.deiconify_approve.ancestor = NULL;
9772
9773                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
9774                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
9775                     {
9776                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
9777                          {
9778                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
9779                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
9780                             e_border_uniconify(ancestor_bd);
9781                          }
9782                     }
9783                }
9784           }
9785 #endif
9786         bd->client.icccm.fetch.transient_for = 0;
9787         rem_change = 1;
9788      }
9789    if (bd->client.icccm.fetch.window_role)
9790      {
9791         char *role = ecore_x_icccm_window_role_get(bd->client.win);
9792         eina_stringshare_replace(&bd->client.icccm.window_role, role);
9793         if (role) free(role);
9794
9795         bd->client.icccm.fetch.window_role = 0;
9796         rem_change = 1;
9797      }
9798    if (bd->client.icccm.fetch.icon_name)
9799      {
9800         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
9801         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
9802         if (icon_name) free(icon_name);
9803
9804         bd->client.icccm.fetch.icon_name = 0;
9805         rem_change = 1;
9806      }
9807    if (bd->client.netwm.fetch.icon_name)
9808      {
9809         char *icon_name;
9810         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
9811         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
9812         if (icon_name) free(icon_name);
9813
9814         bd->client.netwm.fetch.icon_name = 0;
9815         rem_change = 1;
9816      }
9817    if (bd->client.netwm.fetch.icon)
9818      {
9819         int i;
9820         if (bd->client.netwm.icons)
9821           {
9822              for (i = 0; i < bd->client.netwm.num_icons; i++)
9823                {
9824                   free(bd->client.netwm.icons[i].data);
9825                   bd->client.netwm.icons[i].data = NULL;
9826                }
9827              free(bd->client.netwm.icons);
9828           }
9829         bd->client.netwm.icons = NULL;
9830         bd->client.netwm.num_icons = 0;
9831         if (ecore_x_netwm_icons_get(bd->client.win,
9832                                      &bd->client.netwm.icons,
9833                                      &bd->client.netwm.num_icons))
9834           {
9835              // unless the rest of e17 uses border icons OTHER than icon #0
9836              // then free the rest that we don't need anymore.
9837              for (i = 1; i < bd->client.netwm.num_icons; i++)
9838                {
9839                   free(bd->client.netwm.icons[i].data);
9840                   bd->client.netwm.icons[i].data = NULL;
9841                }
9842              bd->client.netwm.num_icons = 1;
9843              bd->changes.icon = 1;
9844           }
9845         bd->client.netwm.fetch.icon = 0;
9846      }
9847    if (bd->client.netwm.fetch.user_time)
9848      {
9849         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
9850         bd->client.netwm.fetch.user_time = 0;
9851      }
9852    if (bd->client.netwm.fetch.strut)
9853      {
9854         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
9855                                              &bd->client.netwm.strut.left,
9856                                              &bd->client.netwm.strut.right,
9857                                              &bd->client.netwm.strut.top,
9858                                              &bd->client.netwm.strut.bottom,
9859                                              &bd->client.netwm.strut.left_start_y,
9860                                              &bd->client.netwm.strut.left_end_y,
9861                                              &bd->client.netwm.strut.right_start_y,
9862                                              &bd->client.netwm.strut.right_end_y,
9863                                              &bd->client.netwm.strut.top_start_x,
9864                                              &bd->client.netwm.strut.top_end_x,
9865                                              &bd->client.netwm.strut.bottom_start_x,
9866                                              &bd->client.netwm.strut.bottom_end_x))
9867           {
9868              ecore_x_netwm_strut_get(bd->client.win,
9869                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
9870                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
9871
9872              bd->client.netwm.strut.left_start_y = 0;
9873              bd->client.netwm.strut.left_end_y = 0;
9874              bd->client.netwm.strut.right_start_y = 0;
9875              bd->client.netwm.strut.right_end_y = 0;
9876              bd->client.netwm.strut.top_start_x = 0;
9877              bd->client.netwm.strut.top_end_x = 0;
9878              bd->client.netwm.strut.bottom_start_x = 0;
9879              bd->client.netwm.strut.bottom_end_x = 0;
9880           }
9881         bd->client.netwm.fetch.strut = 0;
9882      }
9883    if (bd->client.qtopia.fetch.soft_menu)
9884      {
9885         e_hints_window_qtopia_soft_menu_get(bd);
9886         bd->client.qtopia.fetch.soft_menu = 0;
9887         rem_change = 1;
9888      }
9889    if (bd->client.qtopia.fetch.soft_menus)
9890      {
9891         e_hints_window_qtopia_soft_menus_get(bd);
9892         bd->client.qtopia.fetch.soft_menus = 0;
9893         rem_change = 1;
9894      }
9895    if (bd->client.vkbd.fetch.state)
9896      {
9897         e_hints_window_virtual_keyboard_state_get(bd);
9898         bd->client.vkbd.fetch.state = 0;
9899         rem_change = 1;
9900      }
9901    if (bd->client.vkbd.fetch.vkbd)
9902      {
9903         e_hints_window_virtual_keyboard_get(bd);
9904         bd->client.vkbd.fetch.vkbd = 0;
9905         rem_change = 1;
9906      }
9907    if (bd->client.illume.conformant.fetch.conformant)
9908      {
9909         bd->client.illume.conformant.conformant =
9910           ecore_x_e_illume_conformant_get(bd->client.win);
9911         bd->client.illume.conformant.fetch.conformant = 0;
9912      }
9913    if (bd->client.illume.quickpanel.fetch.state)
9914      {
9915         bd->client.illume.quickpanel.state =
9916           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
9917         bd->client.illume.quickpanel.fetch.state = 0;
9918      }
9919    if (bd->client.illume.quickpanel.fetch.quickpanel)
9920      {
9921         bd->client.illume.quickpanel.quickpanel =
9922           ecore_x_e_illume_quickpanel_get(bd->client.win);
9923         bd->client.illume.quickpanel.fetch.quickpanel = 0;
9924      }
9925    if (bd->client.illume.quickpanel.fetch.priority.major)
9926      {
9927         bd->client.illume.quickpanel.priority.major =
9928           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
9929         bd->client.illume.quickpanel.fetch.priority.major = 0;
9930      }
9931    if (bd->client.illume.quickpanel.fetch.priority.minor)
9932      {
9933         bd->client.illume.quickpanel.priority.minor =
9934           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
9935         bd->client.illume.quickpanel.fetch.priority.minor = 0;
9936      }
9937    if (bd->client.illume.quickpanel.fetch.zone)
9938      {
9939         bd->client.illume.quickpanel.zone =
9940           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
9941         bd->client.illume.quickpanel.fetch.zone = 0;
9942      }
9943    if (bd->client.illume.drag.fetch.drag)
9944      {
9945         bd->client.illume.drag.drag =
9946           ecore_x_e_illume_drag_get(bd->client.win);
9947         bd->client.illume.drag.fetch.drag = 0;
9948      }
9949    if (bd->client.illume.drag.fetch.locked)
9950      {
9951         bd->client.illume.drag.locked =
9952           ecore_x_e_illume_drag_locked_get(bd->client.win);
9953         bd->client.illume.drag.fetch.locked = 0;
9954      }
9955    if (bd->client.illume.win_state.fetch.state)
9956      {
9957         bd->client.illume.win_state.state =
9958            ecore_x_e_illume_window_state_get(bd->client.win);
9959         bd->client.illume.win_state.fetch.state = 0;
9960      }
9961    if (bd->changes.shape)
9962      {
9963         Ecore_X_Rectangle *rects;
9964         int num;
9965
9966         bd->changes.shape = 0;
9967         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
9968         if (rects)
9969           {
9970              int cw = 0, ch = 0;
9971
9972              /* This doesn't fix the race, but makes it smaller. we detect
9973               * this and if cw and ch != client w/h then mark this as needing
9974               * a shape change again to fixup next event loop.
9975               */
9976              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9977              if ((cw != bd->client.w) || (ch != bd->client.h))
9978                bd->changes.shape = 1;
9979              if ((num == 1) &&
9980                  (rects[0].x == 0) &&
9981                  (rects[0].y == 0) &&
9982                  ((int)rects[0].width == cw) &&
9983                  ((int)rects[0].height == ch))
9984                {
9985                   if (bd->client.shaped)
9986                     {
9987                        bd->client.shaped = 0;
9988                        if (!bd->bordername)
9989                          bd->client.border.changed = 1;
9990                     }
9991                }
9992              else
9993                {
9994                   if (!bd->client.shaped)
9995                     {
9996                        bd->client.shaped = 1;
9997                        if (!bd->bordername)
9998                          bd->client.border.changed = 1;
9999                     }
10000                }
10001              free(rects);
10002           }
10003         else
10004           {
10005              // FIXME: no rects i think can mean... totally empty window
10006              bd->client.shaped = 0;
10007              if (!bd->bordername)
10008                bd->client.border.changed = 1;
10009           }
10010         bd->need_shape_merge = 1;
10011      }
10012    if (bd->changes.shape_input)
10013      {
10014         Ecore_X_Rectangle *rects;
10015         int num;
10016
10017         bd->changes.shape_input = 0;
10018         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
10019         if (rects)
10020           {
10021              int cw = 0, ch = 0;
10022
10023              /* This doesn't fix the race, but makes it smaller. we detect
10024               * this and if cw and ch != client w/h then mark this as needing
10025               * a shape change again to fixup next event loop.
10026               */
10027              ecore_x_window_size_get(bd->client.win, &cw, &ch);
10028              if ((cw != bd->client.w) || (ch != bd->client.h))
10029                bd->changes.shape_input = 1;
10030              if ((num == 1) &&
10031                  (rects[0].x == 0) &&
10032                  (rects[0].y == 0) &&
10033                  ((int)rects[0].width == cw) &&
10034                  ((int)rects[0].height == ch))
10035                {
10036                   if (bd->shaped_input)
10037                     {
10038                        bd->shaped_input = 0;
10039                        if (!bd->bordername)
10040                          bd->client.border.changed = 1;
10041                     }
10042                }
10043              else
10044                {
10045                   if (!bd->shaped_input)
10046                     {
10047                        bd->shaped_input = 1;
10048                        if (!bd->bordername)
10049                          bd->client.border.changed = 1;
10050                     }
10051                }
10052              free(rects);
10053           }
10054         else
10055           {
10056              bd->shaped_input = 1;
10057              if (!bd->bordername)
10058                bd->client.border.changed = 1;
10059           }
10060         bd->need_shape_merge = 1;
10061      }
10062    if (bd->client.mwm.fetch.hints)
10063      {
10064         int pb;
10065
10066         bd->client.mwm.exists =
10067           ecore_x_mwm_hints_get(bd->client.win,
10068                                 &bd->client.mwm.func,
10069                                 &bd->client.mwm.decor,
10070                                 &bd->client.mwm.input);
10071         pb = bd->client.mwm.borderless;
10072         bd->client.mwm.borderless = 0;
10073         if (bd->client.mwm.exists)
10074           {
10075              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
10076                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
10077                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
10078                bd->client.mwm.borderless = 1;
10079           }
10080         if (bd->client.mwm.borderless != pb)
10081           {
10082              if ((!bd->lock_border) || (!bd->client.border.name))
10083                bd->client.border.changed = 1;
10084           }
10085         bd->client.mwm.fetch.hints = 0;
10086         rem_change = 1;
10087      }
10088    if (bd->client.e.fetch.video_parent)
10089      {
10090         /* unlinking child/parent */
10091         if (bd->client.e.state.video_parent_border != NULL)
10092           {
10093              bd->client.e.state.video_parent_border->client.e.state.video_child =
10094                eina_list_remove
10095                (bd->client.e.state.video_parent_border->client.e.state.video_child,
10096                    bd);
10097           }
10098
10099         ecore_x_window_prop_card32_get(bd->client.win,
10100                                        ECORE_X_ATOM_E_VIDEO_PARENT,
10101                                        &bd->client.e.state.video_parent,
10102                                        1);
10103
10104         /* linking child/parent */
10105         if (bd->client.e.state.video_parent != 0)
10106           {
10107              E_Border *tmp;
10108              Eina_List *l;
10109
10110              EINA_LIST_FOREACH(borders, l, tmp)
10111                if (tmp->client.win == bd->client.e.state.video_parent)
10112                  {
10113                     /* fprintf(stderr, "child added to parent \\o/\n"); */
10114                     bd->client.e.state.video_parent_border = tmp;
10115                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
10116                                                                        bd);
10117                     if (bd->desk != tmp->desk)
10118                       e_border_desk_set(bd, tmp->desk);
10119                     break;
10120                  }
10121           }
10122
10123         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
10124
10125         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
10126         rem_change = 1;
10127      }
10128    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
10129      {
10130         unsigned int xy[2];
10131
10132         ecore_x_window_prop_card32_get(bd->client.win,
10133                                        ECORE_X_ATOM_E_VIDEO_POSITION,
10134                                        xy,
10135                                        2);
10136         bd->client.e.state.video_position.x = xy[0];
10137         bd->client.e.state.video_position.y = xy[1];
10138         bd->client.e.state.video_position.updated = 1;
10139         bd->client.e.fetch.video_position = 0;
10140         bd->x = bd->client.e.state.video_position.x;
10141         bd->y = bd->client.e.state.video_position.y;
10142
10143         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
10144      }
10145    if (bd->client.netwm.update.state)
10146      {
10147         e_hints_window_state_set(bd);
10148         /* Some stats might change the border, like modal */
10149         if (((!bd->lock_border) || (!bd->client.border.name)) &&
10150             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10151           {
10152              bd->client.border.changed = 1;
10153           }
10154         if (bd->parent)
10155           {
10156              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10157                {
10158                   bd->parent->modal = bd;
10159                   if (bd->parent->focused)
10160                     e_border_focus_set(bd, 1, 1);
10161                }
10162           }
10163         else if (bd->leader)
10164           {
10165              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10166                {
10167                   bd->leader->modal = bd;
10168                   if (bd->leader->focused)
10169                     e_border_focus_set(bd, 1, 1);
10170                   else
10171                     {
10172                        Eina_List *l;
10173                        E_Border *child;
10174
10175                        EINA_LIST_FOREACH(bd->leader->group, l, child)
10176                          {
10177                             if ((child != bd) && (child->focused))
10178                               e_border_focus_set(bd, 1, 1);
10179                          }
10180                     }
10181                }
10182           }
10183         bd->client.netwm.update.state = 0;
10184      }
10185
10186    if (bd->new_client)
10187      {
10188         E_Event_Border_Add *ev;
10189         E_Exec_Instance *inst;
10190
10191         ev = E_NEW(E_Event_Border_Add, 1);
10192         ev->border = bd;
10193         e_object_ref(E_OBJECT(bd));
10194         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
10195         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
10196
10197         if ((!bd->lock_border) || (!bd->client.border.name))
10198           bd->client.border.changed = 1;
10199
10200           {
10201              char *str = NULL;
10202
10203              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
10204                  ((bd->client.icccm.client_leader > 0) &&
10205                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
10206                 )
10207                {
10208                   if (!strncmp(str, "E_START|", 8))
10209                     {
10210                        int id;
10211
10212                        id = atoi(str + 8);
10213                        if (id > 0) bd->client.netwm.startup_id = id;
10214                     }
10215                   free(str);
10216                }
10217           }
10218         /* It's ok not to have fetch flag, should only be set on startup
10219          *     * and not changed. */
10220         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
10221           {
10222              if (bd->client.icccm.client_leader)
10223                {
10224                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
10225                     bd->client.netwm.pid = -1;
10226                }
10227              else
10228                bd->client.netwm.pid = -1;
10229           }
10230
10231         if (!bd->re_manage)
10232           {
10233              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
10234                                                         bd->client.netwm.pid);
10235              if ((inst) && (inst->used == 0))
10236                {
10237                   E_Zone *zone;
10238                   E_Desk *desk;
10239
10240                   inst->used++;
10241                   zone = e_container_zone_number_get(bd->zone->container,
10242                                                      inst->screen);
10243                   if (zone) e_border_zone_set(bd, zone);
10244                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
10245                                           inst->desk_y);
10246                   if (desk) e_border_desk_set(bd, desk);
10247                   e_exec_instance_found(inst);
10248                }
10249
10250              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
10251                {
10252                   E_Border *bdl = NULL;
10253
10254                   bdl = bd->parent;
10255                   if (!bdl)
10256                     {
10257                        if (bd->leader) bdl = bd->leader;
10258                     }
10259                   if (!bdl)
10260                     {
10261                        E_Border *child;
10262                        E_Border_List *bl;
10263
10264                        bl = e_container_border_list_first(bd->zone->container);
10265                        while ((child = e_container_border_list_next(bl)))
10266                          {
10267                             if (child == bd) continue;
10268                             if (e_object_is_del(E_OBJECT(child))) continue;
10269                             if ((bd->client.icccm.client_leader) &&
10270                                 (child->client.icccm.client_leader ==
10271                                     bd->client.icccm.client_leader))
10272                               {
10273                                  bdl = child;
10274                                  break;
10275                               }
10276                          }
10277                        e_container_border_list_free(bl);
10278                     }
10279                   if (bdl)
10280                     {
10281                        if (bdl->zone)
10282                          e_border_zone_set(bd, bdl->zone);
10283                        if (bdl->desk)
10284                          e_border_desk_set(bd, bdl->desk);
10285                        else
10286                          e_border_stick(bd);
10287                     }
10288                }
10289           }
10290      }
10291
10292 #ifdef _F_USE_DESK_WINDOW_PROFILE_
10293    if (need_desk_set)
10294      {
10295         E_Container *con = bd->zone->container;
10296         E_Desk *desk = NULL;
10297         Eina_List *l;
10298         const char *str;
10299         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
10300           {
10301              desk = e_container_desk_window_profile_get(con, str);
10302              if (desk)
10303                {
10304                   if (bd->desk != desk)
10305                     {
10306                        bd->client.e.state.profile = eina_stringshare_add(str);
10307                        if (bd->zone != desk->zone)
10308                          e_border_zone_set(bd, desk->zone);
10309                        e_border_desk_set(bd, desk);
10310                     }
10311                   break;
10312                }
10313           }
10314      }
10315 #endif
10316
10317    /* PRE_POST_FETCH calls e_remember apply for new client */
10318    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
10319    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
10320    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
10321
10322 #ifdef _F_ZONE_WINDOW_ROTATION_
10323    if (e_config->wm_win_rotation)
10324      {
10325         if (need_rotation_set)
10326           {
10327              Eina_Bool hint = EINA_FALSE;
10328              int ang = 0;
10329              int x, y, w, h, move;
10330
10331              ELB(ELBT_ROT, "NEED ROT", bd->client.win);
10332              bd->client.e.state.rot.changes = _e_border_rotation_angle_get(bd);
10333
10334              if (bd->client.e.state.rot.changes == -1)
10335                {
10336                   ang = bd->client.e.state.rot.curr;
10337
10338                   hint = _e_border_rotation_geom_get(bd, bd->zone, ang, &x, &y, &w, &h, &move);
10339                   if (hint)
10340                     {
10341                        _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
10342                        ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
10343                             bd->client.icccm.name, x, y, w, h);
10344                     }
10345                }
10346              else bd->changed = 1;
10347           }
10348      }
10349 #endif
10350
10351    if (bd->need_reparent)
10352      {
10353         if (!bd->internal)
10354           ecore_x_window_save_set_add(bd->client.win);
10355         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
10356         if (bd->visible)
10357           {
10358              if ((bd->new_client) && (bd->internal) &&
10359                  (bd->internal_ecore_evas))
10360                ecore_evas_show(bd->internal_ecore_evas);
10361              ecore_x_window_show(bd->client.win);
10362           }
10363         bd->need_reparent = 0;
10364      }
10365
10366    if ((bd->client.border.changed) && (!bd->shaded) &&
10367        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10368      {
10369         const char *bordername;
10370
10371         if (bd->fullscreen)
10372           bordername = "borderless";
10373         else if (bd->bordername)
10374           bordername = bd->bordername;
10375         else if ((bd->client.mwm.borderless) || (bd->borderless))
10376           bordername = "borderless";
10377         else if (((bd->client.icccm.transient_for != 0) ||
10378                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
10379                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10380                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10381           bordername = "noresize_dialog";
10382         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10383                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10384           bordername = "noresize";
10385         else if (bd->client.shaped)
10386           bordername = "shaped";
10387         else if ((!bd->client.icccm.accepts_focus) &&
10388                  (!bd->client.icccm.take_focus))
10389           bordername = "nofocus";
10390         else if (bd->client.icccm.urgent)
10391           bordername = "urgent";
10392         else if ((bd->client.icccm.transient_for != 0) ||
10393                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10394           bordername = "dialog";
10395         else if (bd->client.netwm.state.modal)
10396           bordername = "modal";
10397         else if ((bd->client.netwm.state.skip_taskbar) ||
10398                  (bd->client.netwm.state.skip_pager))
10399           bordername = "skipped";
10400         else if ((bd->internal) && (bd->client.icccm.class) &&
10401                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
10402           bordername = "internal_fileman";
10403         else
10404           bordername = e_config->theme_default_border_style;
10405         if (!bordername) bordername = "default";
10406
10407         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
10408           {
10409              Evas_Object *o;
10410              char buf[4096];
10411              int ok;
10412
10413              bd->changes.border = 1;
10414              eina_stringshare_replace(&bd->client.border.name, bordername);
10415
10416              if (bd->bg_object)
10417                {
10418                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
10419                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
10420                   bd->changes.size = 1;
10421                   evas_object_del(bd->bg_object);
10422                }
10423              o = edje_object_add(bd->bg_evas);
10424              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
10425              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10426              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
10427                {
10428                   if (bd->client.border.name != e_config->theme_default_border_style)
10429                     {
10430                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
10431                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10432                     }
10433                   if (!ok)
10434                     {
10435                        ok = e_theme_edje_object_set(o, "base/theme/borders",
10436                                                     "e/widgets/border/default/border");
10437                        if (ok)
10438                          {
10439                             /* Reset default border style to default */
10440                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
10441                             e_config_save_queue();
10442                          }
10443                     }
10444                }
10445
10446              bd->shaped = 0;
10447              if (ok)
10448                {
10449                   const char *shape_option, *argb_option;
10450                   int use_argb = 0;
10451
10452                   bd->bg_object = o;
10453
10454                   if ((e_config->use_composite) && (!bd->client.argb))
10455                     {
10456                        argb_option = edje_object_data_get(o, "argb");
10457                        if ((argb_option) && (!strcmp(argb_option, "1")))
10458                          use_argb = 1;
10459
10460                        if (use_argb != bd->argb)
10461                          _e_border_frame_replace(bd, use_argb);
10462
10463                        o = bd->bg_object;
10464                     }
10465
10466                   if (!bd->argb)
10467                     {
10468                        shape_option = edje_object_data_get(o, "shaped");
10469                        if ((shape_option) && (!strcmp(shape_option, "1")))
10470                          bd->shaped = 1;
10471                     }
10472
10473                   if (bd->client.netwm.name)
10474                     edje_object_part_text_set(o, "e.text.title",
10475                                               bd->client.netwm.name);
10476                   else if (bd->client.icccm.title)
10477                     edje_object_part_text_set(o, "e.text.title",
10478                                               bd->client.icccm.title);
10479                }
10480              else
10481                {
10482                   evas_object_del(o);
10483                   bd->bg_object = NULL;
10484                }
10485
10486              _e_border_client_inset_calc(bd);
10487
10488              bd->w += (bd->client_inset.l + bd->client_inset.r);
10489              bd->h += (bd->client_inset.t + bd->client_inset.b);
10490              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
10491              bd->changes.size = 1;
10492              /*  really needed ? */
10493              ecore_x_window_move(bd->client.shell_win,
10494                                  bd->client_inset.l,
10495                                  bd->client_inset.t);
10496
10497              if (bd->maximized != E_MAXIMIZE_NONE)
10498                {
10499                   E_Maximize maximized = bd->maximized;
10500
10501                   /* to force possible resizes */
10502                   bd->maximized = E_MAXIMIZE_NONE;
10503
10504                   _e_border_maximize(bd, maximized);
10505
10506                   /* restore maximized state */
10507                   bd->maximized = maximized;
10508
10509                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
10510                                                bd->maximized & E_MAXIMIZE_VERTICAL);
10511                }
10512              if (bd->bg_object)
10513                {
10514                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
10515                                                   _e_border_cb_signal_bind, bd);
10516                   if (bd->focused)
10517                     {
10518                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
10519                        if (bd->icon_object)
10520                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10521                     }
10522                   if (bd->shaded)
10523                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
10524                   if (bd->sticky)
10525                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
10526                   if (bd->hung)
10527                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
10528                   // FIXME: in eval -do differently
10529                   //         edje_object_message_signal_process(bd->bg_object);
10530                   //         e_border_frame_recalc(bd);
10531
10532                   evas_object_move(bd->bg_object, 0, 0);
10533                   evas_object_resize(bd->bg_object, bd->w, bd->h);
10534                   evas_object_show(bd->bg_object);
10535                }
10536           }
10537         bd->client.border.changed = 0;
10538
10539         if (bd->icon_object)
10540           {
10541              if (bd->bg_object)
10542                {
10543                   evas_object_show(bd->icon_object);
10544                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10545                }
10546              else
10547                evas_object_hide(bd->icon_object);
10548           }
10549      }
10550
10551    if (rem_change) e_remember_update(bd);
10552
10553    if (change_urgent)
10554      {
10555         E_Event_Border_Urgent_Change *ev;
10556
10557         if (bd->client.icccm.urgent)
10558           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
10559         else
10560           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
10561
10562         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
10563         ev->border = bd;
10564         e_object_ref(E_OBJECT(bd));
10565         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
10566                         _e_border_event_border_urgent_change_free, NULL);
10567      }
10568
10569    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10570 }
10571
10572 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10573 static void
10574 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10575 {
10576    E_Border* temp_bd = NULL;
10577    E_Border* top_focusable_bd = NULL;
10578    Eina_Bool is_fully_obscured = EINA_FALSE;
10579    Ecore_X_XRegion *visible_region = NULL;
10580    Ecore_X_XRegion *win_region = NULL;
10581    Ecore_X_Rectangle visible_rect, win_rect;
10582    E_Border_List *bl;
10583
10584    // set the entire visible region as a root geometry
10585    visible_rect.x = bd->zone->x;
10586    visible_rect.y = bd->zone->y;
10587    visible_rect.width = bd->zone->w;
10588    visible_rect.height = bd->zone->h;
10589
10590    visible_region = ecore_x_xregion_new();
10591    if (!visible_region) return;
10592
10593    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10594
10595    bl = e_container_border_list_last(bd->zone->container);
10596    while ((temp_bd = e_container_border_list_prev(bl)))
10597      {
10598         if (temp_bd == bd) break;
10599
10600         if (temp_bd == focused) continue;
10601         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10602         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10603         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10604             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10605             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10606             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10607             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10608             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10609             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10610           {
10611              if (!top_focusable_bd)
10612                {
10613                   top_focusable_bd = temp_bd;
10614                }
10615
10616              win_rect.x = temp_bd->x;
10617              win_rect.y = temp_bd->y;
10618              win_rect.width = temp_bd->w;
10619              win_rect.height = temp_bd->h;
10620
10621              // if it stick out or is bigger than the entire visible region,
10622              // clip it by the entire visible's geometry.
10623              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10624                                   win_rect.width, win_rect.height,
10625                                   visible_rect.x, visible_rect.y,
10626                                   (int)(visible_rect.width), (int)(visible_rect.height));
10627
10628              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10629                {
10630                   win_region = ecore_x_xregion_new();
10631                   if (win_region)
10632                     {
10633                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10634                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10635                        ecore_x_xregion_free(win_region);
10636                        win_region = NULL;
10637
10638                        if (ecore_x_xregion_is_empty(visible_region))
10639                          {
10640                             is_fully_obscured = EINA_TRUE;
10641                             break;
10642                          }
10643                     }
10644                }
10645           }
10646      }
10647
10648    if (is_fully_obscured == EINA_TRUE)
10649      {
10650         e_border_focus_set(top_focusable_bd, 1, 1);
10651      }
10652    else
10653      {
10654         e_border_focus_set(bd, 1, 1);
10655      }
10656
10657    if (visible_region) ecore_x_xregion_free(visible_region);
10658    e_container_border_list_free(bl);
10659 }
10660
10661 static void
10662 _e_border_latest_stacked_focus(E_Border *bd)
10663 {
10664    E_Border *temp_bd;
10665    int root_w, root_h;
10666
10667    root_w = bd->zone->w;
10668    root_h = bd->zone->h;
10669
10670    Eina_List *l;
10671    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10672      {
10673         if (bd == temp_bd) continue;
10674         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10675         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10676
10677         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10678             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10679             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10680             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10681             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10682             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10683             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10684           {
10685              _e_border_latest_stacked_focus_check_set(temp_bd);
10686              break;
10687           }
10688      }
10689 }
10690
10691 static void
10692 _e_border_check_stack (E_Border *bd)
10693 {
10694    E_Border* temp_bd = NULL;
10695    E_Border* top_bd = NULL;
10696    int passed_focus = 0;
10697    int passed = 0;
10698    int root_w = bd->zone->w;
10699    int root_h = bd->zone->h;
10700
10701    E_Border_List *bl;
10702    bl = e_container_border_list_last(bd->zone->container);
10703    while ((temp_bd = e_container_border_list_prev(bl)))
10704      {
10705         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10706         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10707         if ((temp_bd != bd) &&
10708             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10709
10710         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10711            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10712            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10713            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10714            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10715            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10716            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10717           {
10718              if (bd == temp_bd)
10719                {
10720                   if (!passed)
10721                     {
10722                        e_border_focus_set_with_pointer(bd);
10723                        break;
10724                     }
10725                   else
10726                     {
10727                        if (!passed_focus)
10728                          {
10729                             e_border_focus_set_with_pointer(top_bd);
10730                          }
10731                        break;
10732                     }
10733                }
10734              else
10735                {
10736                   if (!passed)
10737                     {
10738                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10739                          {
10740                             if (!bd->lock_focus_out)
10741                               {
10742                                  e_border_focus_latest_set(bd);
10743                               }
10744                          }
10745                     }
10746                }
10747
10748              if (!passed)
10749                {
10750                   passed = 1;
10751                   top_bd = temp_bd;
10752                }
10753
10754              if (temp_bd == focused)
10755                {
10756                   passed_focus = 1;
10757                }
10758           }
10759      }
10760    e_container_border_list_free(bl);
10761 }
10762
10763 static void
10764 _e_border_focus_top_stack_set(E_Border* bd)
10765 {
10766    E_Border *temp_bd;
10767    int root_w, root_h;
10768
10769    root_w = bd->zone->w;
10770    root_h = bd->zone->h;
10771
10772    E_Border_List *bl;
10773    bl = e_container_border_list_last(bd->zone->container);
10774    while ((temp_bd = e_container_border_list_prev(bl)))
10775      {
10776         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10777         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10778         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
10779
10780         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10781            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10782            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10783            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10784            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10785            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10786            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10787           {
10788              if (!temp_bd->focused)
10789                {
10790                   /* this border is the top of the latest stack */
10791                   e_border_focus_set (temp_bd, 1, 1);
10792                }
10793              break;
10794           }
10795      }
10796    e_container_border_list_free(bl);
10797 }
10798 #endif
10799
10800 static void
10801 _e_border_eval(E_Border *bd)
10802 {
10803    E_Event_Border_Property *event;
10804    E_Border_Pending_Move_Resize *pnd;
10805    int rem_change = 0;
10806    int send_event = 1;
10807
10808    if (e_object_is_del(E_OBJECT(bd)))
10809      {
10810         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
10811         bd->changed = 0;
10812         return;
10813      }
10814
10815    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
10816
10817    if (bd->new_client)
10818      {
10819         int zx = 0, zy = 0, zw = 0, zh = 0;
10820
10821         if (bd->zone)
10822           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
10823
10824         /*
10825          * Limit maximum size of windows to useful geometry
10826          */
10827         // TODO: temoporary limited maximize algorithm
10828         // ->
10829         /*if (bd->w > zw)
10830           rw = zw;
10831           else
10832           rw = bd->w;
10833
10834           if (bd->h > zh)
10835           rh = zh;
10836           else
10837           rh = bd->h;
10838
10839           if ((rw != bd->w) || (rh != bd->h))
10840           {
10841           bd->w = rw;
10842           bd->h = rh;
10843           e_border_resize (bd, bd->w, bd->h);
10844           }*/
10845         // <-
10846
10847         if (bd->re_manage)
10848           {
10849              bd->x -= bd->client_inset.l;
10850              bd->y -= bd->client_inset.t;
10851              bd->changes.pos = 1;
10852              bd->placed = 1;
10853           }
10854         else if ((!bd->placed) && (bd->client.icccm.request_pos))
10855           {
10856
10857              Ecore_X_Window_Attributes *att;
10858              int bw;
10859
10860              att = &bd->client.initial_attributes;
10861              bw = att->border * 2;
10862              switch (bd->client.icccm.gravity)
10863                {
10864                 case ECORE_X_GRAVITY_N:
10865                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10866                    bd->y = att->y;
10867                    break;
10868
10869                 case ECORE_X_GRAVITY_NE:
10870                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10871                    bd->y = att->y;
10872                    break;
10873
10874                 case ECORE_X_GRAVITY_E:
10875                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10876                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10877                    break;
10878
10879                 case ECORE_X_GRAVITY_SE:
10880                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10881                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10882                    break;
10883
10884                 case ECORE_X_GRAVITY_S:
10885                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10886                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10887                    break;
10888
10889                 case ECORE_X_GRAVITY_SW:
10890                    bd->x = att->x;
10891                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10892                    break;
10893
10894                 case ECORE_X_GRAVITY_W:
10895                    bd->x = att->x;
10896                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10897                    break;
10898
10899                 case ECORE_X_GRAVITY_CENTER:
10900                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10901                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10902                    break;
10903
10904                 case ECORE_X_GRAVITY_NW:
10905                 default:
10906                    bd->x = att->x;
10907                    bd->y = att->y;
10908                }
10909
10910              /*
10911               * This ensures that windows that like to open with a x/y
10912               * position smaller than returned by e_zone_useful_geometry_get()
10913               * are moved to useful positions.
10914               */
10915              // ->
10916              if (e_config->geometry_auto_move)
10917                {
10918                   if (bd->x < zx)
10919                     bd->x = zx;
10920
10921                   if (bd->y < zy)
10922                     bd->y = zy;
10923
10924                   if (bd->x + bd->w > zx + zw)
10925                     bd->x = zx + zw - bd->w;
10926
10927                   if (bd->y + bd->h > zy + zh)
10928                     bd->y = zy + zh - bd->h;
10929                   // <--
10930
10931                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
10932                     {
10933                        bd->changes.pos = 1;
10934                        bd->placed = 1;
10935                     }
10936                }
10937              else
10938                {
10939                   bd->changes.pos = 1;
10940                   bd->placed = 1;
10941                }
10942           }
10943         if (!bd->placed)
10944           {
10945              /* FIXME: special placement for dialogs etc. etc. etc goes
10946               * here */
10947              /* FIXME: what if parent is not on this desktop - or zone? */
10948              if ((bd->parent) && (bd->parent->visible))
10949                {
10950                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
10951                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
10952                   bd->changes.pos = 1;
10953                   bd->placed = 1;
10954                }
10955 #if 0
10956              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10957                {
10958                   /* TODO: Place in center of group */
10959                }
10960 #endif
10961              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
10962                {
10963                   bd->x = zx + ((zw - bd->w) / 2);
10964                   bd->y = zy + ((zh - bd->h) / 2);
10965                   bd->changes.pos = 1;
10966                   bd->placed = 1;
10967                }
10968           }
10969         if (!bd->placed)
10970           {
10971              Eina_List *skiplist = NULL;
10972              int new_x, new_y;
10973
10974              if (zw > bd->w)
10975                new_x = zx + (rand() % (zw - bd->w));
10976              else
10977                new_x = zx;
10978              if (zh > bd->h)
10979                new_y = zy + (rand() % (zh - bd->h));
10980              else
10981                new_y = zy;
10982
10983              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
10984                {
10985                   skiplist = eina_list_append(skiplist, bd);
10986                   if (bd->desk)
10987                     e_place_desk_region_smart(bd->desk, skiplist,
10988                                               bd->x, bd->y, bd->w, bd->h,
10989                                               &new_x, &new_y);
10990                   else
10991                     e_place_zone_region_smart(bd->zone, skiplist,
10992                                               bd->x, bd->y, bd->w, bd->h,
10993                                               &new_x, &new_y);
10994                   eina_list_free(skiplist);
10995                }
10996              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
10997                {
10998                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
10999                                       &new_x, &new_y);
11000                }
11001              else
11002                {
11003                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
11004                                       bd->client_inset.t, &new_x, &new_y);
11005                }
11006              bd->x = new_x;
11007              bd->y = new_y;
11008              bd->changes.pos = 1;
11009           }
11010
11011         EINA_LIST_FREE(bd->pending_move_resize, pnd)
11012           {
11013              if ((!bd->lock_client_location) && (pnd->move))
11014                {
11015                   bd->x = pnd->x;
11016                   bd->y = pnd->y;
11017                   bd->changes.pos = 1;
11018                   bd->placed = 1;
11019                   if (pnd->without_border)
11020                     {
11021                        bd->x -= bd->client_inset.l;
11022                        bd->y -= bd->client_inset.t;
11023                     }
11024                }
11025              if ((!bd->lock_client_size) && (pnd->resize))
11026                {
11027                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
11028                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
11029                   bd->client.w = pnd->w;
11030                   bd->client.h = pnd->h;
11031                   bd->changes.size = 1;
11032                }
11033
11034              free(pnd);
11035           }
11036
11037         /* Recreate state */
11038         e_hints_window_init(bd);
11039         if ((bd->client.e.state.centered) &&
11040             ((!bd->remember) ||
11041              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
11042           {
11043              bd->x = zx + (zw - bd->w) / 2;
11044              bd->y = zy + (zh - bd->h) / 2;
11045              bd->changes.pos = 1;
11046              bd->placed = 1;
11047           }
11048
11049         _e_border_client_move_resize_send(bd);
11050
11051         /* if the explicit geometry request asks for the app to be
11052          * in another zone - well move it there */
11053         {
11054            E_Zone *zone;
11055
11056            zone = e_container_zone_at_point_get(bd->zone->container,
11057                                                 bd->x + (bd->w / 2),
11058                                                 bd->y + (bd->h / 2));
11059            if (!zone)
11060              zone = e_container_zone_at_point_get(bd->zone->container,
11061                                                   bd->x,
11062                                                   bd->y);
11063            if (!zone)
11064              zone = e_container_zone_at_point_get(bd->zone->container,
11065                                                   bd->x + bd->w - 1,
11066                                                   bd->y);
11067            if (!zone)
11068              zone = e_container_zone_at_point_get(bd->zone->container,
11069                                                   bd->x + bd->w - 1,
11070                                                   bd->y + bd->h - 1);
11071            if (!zone)
11072              zone = e_container_zone_at_point_get(bd->zone->container,
11073                                                   bd->x,
11074                                                   bd->y + bd->h - 1);
11075            if ((zone) && (zone != bd->zone))
11076              e_border_zone_set(bd, zone);
11077         }
11078      }
11079
11080    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
11081
11082    /* effect changes to the window border itself */
11083    if ((bd->changes.shading))
11084      {
11085         /*  show at start of unshade (but don't hide until end of shade) */
11086         if (bd->shaded)
11087           ecore_x_window_raise(bd->client.shell_win);
11088         bd->changes.shading = 0;
11089         rem_change = 1;
11090      }
11091    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
11092      {
11093         if (bd->shaded)
11094           ecore_x_window_lower(bd->client.shell_win);
11095         else
11096           ecore_x_window_raise(bd->client.shell_win);
11097         bd->changes.shaded = 0;
11098         rem_change = 1;
11099      }
11100    else if ((bd->changes.shaded) && (bd->changes.pos))
11101      {
11102         if (bd->shaded)
11103           ecore_x_window_lower(bd->client.shell_win);
11104         else
11105           ecore_x_window_raise(bd->client.shell_win);
11106         bd->changes.size = 1;
11107         bd->changes.shaded = 0;
11108         rem_change = 1;
11109      }
11110    else if ((bd->changes.shaded) && (bd->changes.size))
11111      {
11112         if (bd->shaded)
11113           ecore_x_window_lower(bd->client.shell_win);
11114         else
11115           ecore_x_window_raise(bd->client.shell_win);
11116         bd->changes.shaded = 0;
11117         rem_change = 1;
11118      }
11119    else if (bd->changes.shaded)
11120      {
11121         if (bd->shaded)
11122           ecore_x_window_lower(bd->client.shell_win);
11123         else
11124           ecore_x_window_raise(bd->client.shell_win);
11125         bd->changes.size = 1;
11126         bd->changes.shaded = 0;
11127         rem_change = 1;
11128      }
11129
11130    if (bd->changes.size)
11131      {
11132         int x = 0, y = 0, xx = 0, yy = 0;
11133
11134         if ((bd->shaded) && (!bd->shading))
11135           {
11136              evas_obscured_clear(bd->bg_evas);
11137           }
11138         else
11139           {
11140              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
11141              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
11142
11143              evas_obscured_clear(bd->bg_evas);
11144              evas_obscured_rectangle_add(bd->bg_evas,
11145                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
11146
11147              if (bd->shading)
11148                {
11149                   if (bd->shade.dir == E_DIRECTION_UP)
11150                     {
11151                        y = yy - bd->client.h;
11152                     }
11153                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11154                     {
11155                        x = xx - bd->client.w;
11156                     }
11157                }
11158           }
11159
11160         if (bd->client.e.state.video)
11161           {
11162              if (bd->client.e.state.video_position.updated)
11163                {
11164                   ecore_x_window_move(bd->win,
11165                                       bd->client.e.state.video_parent_border->x +
11166                                       bd->client.e.state.video_parent_border->client_inset.l +
11167                                       bd->client.e.state.video_parent_border->fx.x +
11168                                       bd->client.e.state.video_position.x,
11169                                       bd->client.e.state.video_parent_border->y +
11170                                       bd->client.e.state.video_parent_border->client_inset.t +
11171                                       bd->client.e.state.video_parent_border->fx.y +
11172                                       bd->client.e.state.video_position.y);
11173                   bd->client.e.state.video_position.updated = 0;
11174                }
11175           }
11176         else if (!bd->changes.pos)
11177           {
11178              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11179              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11180              bd->post_resize = 1;
11181           }
11182         else
11183           {
11184              E_Border *tmp;
11185              Eina_List *l;
11186
11187              ecore_x_window_move_resize(bd->win,
11188                                         bd->x + bd->fx.x,
11189                                         bd->y + bd->fx.y,
11190                                         bd->w, bd->h);
11191
11192              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
11193                ecore_x_window_move(tmp->win,
11194                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
11195                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
11196           }
11197
11198         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
11199
11200         if ((!bd->shaded) || (bd->shading))
11201           ecore_x_window_move_resize(bd->client.shell_win,
11202                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
11203
11204         if (bd->internal_ecore_evas)
11205           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
11206         else if (!bd->client.e.state.video)
11207           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
11208
11209         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
11210         evas_object_resize(bd->bg_object, bd->w, bd->h);
11211         e_container_shape_resize(bd->shape, bd->w, bd->h);
11212         if (bd->changes.pos)
11213           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11214
11215         _e_border_client_move_resize_send(bd);
11216
11217         bd->changes.pos = 0;
11218         bd->changes.size = 0;
11219         rem_change = 1;
11220      }
11221    else if (bd->changes.pos)
11222      {
11223         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11224         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11225         bd->post_move = 1;
11226
11227         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11228
11229         _e_border_client_move_resize_send(bd);
11230
11231         bd->changes.pos = 0;
11232         rem_change = 1;
11233      }
11234
11235    if (bd->changes.reset_gravity)
11236      {
11237         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
11238         bd->changes.reset_gravity = 0;
11239         rem_change = 1;
11240      }
11241
11242    if (bd->need_shape_merge)
11243      {
11244         _e_border_shape_input_rectangle_set(bd);
11245         if ((bd->shaped) || (bd->client.shaped))
11246           {
11247              Ecore_X_Window twin, twin2;
11248              int x, y;
11249
11250              twin = ecore_x_window_override_new
11251                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
11252              if (bd->shaped)
11253                ecore_x_window_shape_window_set(twin, bd->bg_win);
11254              else
11255                {
11256                   Ecore_X_Rectangle rects[4];
11257
11258                   rects[0].x = 0;
11259                   rects[0].y = 0;
11260                   rects[0].width = bd->w;
11261                   rects[0].height = bd->client_inset.t;
11262                   rects[1].x = 0;
11263                   rects[1].y = bd->client_inset.t;
11264                   rects[1].width = bd->client_inset.l;
11265                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11266                   rects[2].x = bd->w - bd->client_inset.r;
11267                   rects[2].y = bd->client_inset.t;
11268                   rects[2].width = bd->client_inset.r;
11269                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11270                   rects[3].x = 0;
11271                   rects[3].y = bd->h - bd->client_inset.b;
11272                   rects[3].width = bd->w;
11273                   rects[3].height = bd->client_inset.b;
11274                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
11275                }
11276              twin2 = ecore_x_window_override_new
11277                (bd->zone->container->scratch_win, 0, 0,
11278                 bd->w - bd->client_inset.l - bd->client_inset.r,
11279                 bd->h - bd->client_inset.t - bd->client_inset.b);
11280              x = 0;
11281              y = 0;
11282              if ((bd->shading) || (bd->shaded))
11283                {
11284                   if (bd->shade.dir == E_DIRECTION_UP)
11285                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
11286                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11287                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
11288                }
11289              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
11290                                                 x, y);
11291              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
11292                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
11293                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
11294              ecore_x_window_shape_window_add_xy(twin, twin2,
11295                                                 bd->client_inset.l,
11296                                                 bd->client_inset.t);
11297              ecore_x_window_free(twin2);
11298              ecore_x_window_shape_window_set(bd->win, twin);
11299              ecore_x_window_free(twin);
11300           }
11301         else
11302           ecore_x_window_shape_mask_set(bd->win, 0);
11303         //      bd->need_shape_export = 1;
11304         bd->need_shape_merge = 0;
11305      }
11306
11307    if (bd->need_shape_export)
11308      {
11309         Ecore_X_Rectangle *rects, *orects;
11310         int num;
11311
11312         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
11313         if (rects)
11314           {
11315              int changed;
11316
11317              changed = 1;
11318              if ((num == bd->shape_rects_num) && (bd->shape_rects))
11319                {
11320                   int i;
11321
11322                   orects = bd->shape_rects;
11323                   changed = 0;
11324                   for (i = 0; i < num; i++)
11325                     {
11326                        if (rects[i].x < 0)
11327                          {
11328                             rects[i].width -= rects[i].x;
11329                             rects[i].x = 0;
11330                          }
11331                        if ((rects[i].x + (int)rects[i].width) > bd->w)
11332                          rects[i].width = rects[i].width - rects[i].x;
11333                        if (rects[i].y < 0)
11334                          {
11335                             rects[i].height -= rects[i].y;
11336                             rects[i].y = 0;
11337                          }
11338                        if ((rects[i].y + (int)rects[i].height) > bd->h)
11339                          rects[i].height = rects[i].height - rects[i].y;
11340
11341                        if ((orects[i].x != rects[i].x) ||
11342                            (orects[i].y != rects[i].y) ||
11343                            (orects[i].width != rects[i].width) ||
11344                            (orects[i].height != rects[i].height))
11345                          {
11346                             changed = 1;
11347                             break;
11348                          }
11349                     }
11350                }
11351              if (changed)
11352                {
11353                   if (bd->client.shaped)
11354                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
11355                   else
11356                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
11357                   E_FREE(bd->shape_rects);
11358                   bd->shape_rects = rects;
11359                   bd->shape_rects_num = num;
11360                   e_container_shape_rects_set(bd->shape, rects, num);
11361                }
11362              else
11363                free(rects);
11364           }
11365         else
11366           {
11367              E_FREE(bd->shape_rects);
11368              bd->shape_rects = NULL;
11369              bd->shape_rects_num = 0;
11370              e_container_shape_rects_set(bd->shape, NULL, 0);
11371           }
11372         bd->need_shape_export = 0;
11373      }
11374
11375    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
11376      {
11377         int x, y;
11378
11379         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
11380         if ((!bd->placed) && (!bd->re_manage) &&
11381             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
11382             (!((bd->client.icccm.transient_for != 0) ||
11383                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
11384             (!bdmove) && (!bdresize))
11385           {
11386              /* Set this window into moving state */
11387
11388              bd->cur_mouse_action = e_action_find("window_move");
11389              if (bd->cur_mouse_action)
11390                {
11391                   if ((!bd->cur_mouse_action->func.end_mouse) &&
11392                       (!bd->cur_mouse_action->func.end))
11393                     bd->cur_mouse_action = NULL;
11394                   if (bd->cur_mouse_action)
11395                     {
11396                        bd->x = x - (bd->w >> 1);
11397                        bd->y = y - (bd->client_inset.t >> 1);
11398                        bd->changed = 1;
11399                        bd->changes.pos = 1;
11400
11401                        _e_border_client_move_resize_send(bd);
11402                     }
11403                }
11404           }
11405
11406         _e_border_show(bd);
11407
11408         if (bd->cur_mouse_action)
11409           {
11410              bd->moveinfo.down.x = bd->x + bd->fx.x;
11411              bd->moveinfo.down.y = bd->y + bd->fx.y;
11412              bd->moveinfo.down.w = bd->w;
11413              bd->moveinfo.down.h = bd->h;
11414              bd->mouse.current.mx = x;
11415              bd->mouse.current.my = y;
11416              bd->moveinfo.down.button = 0;
11417              bd->moveinfo.down.mx = x;
11418              bd->moveinfo.down.my = y;
11419
11420              grabbed = 1;
11421              e_object_ref(E_OBJECT(bd->cur_mouse_action));
11422              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
11423              if (e_config->border_raise_on_mouse_action)
11424                e_border_raise(bd);
11425              e_border_focus_set(bd, 1, 1);
11426           }
11427         bd->changes.visible = 0;
11428         rem_change = 1;
11429      }
11430
11431    if (bd->changes.icon)
11432      {
11433         if (bd->desktop)
11434           {
11435              efreet_desktop_free(bd->desktop);
11436              bd->desktop = NULL;
11437           }
11438         if (bd->icon_object)
11439           {
11440              evas_object_del(bd->icon_object);
11441              bd->icon_object = NULL;
11442           }
11443         if (bd->remember && bd->remember->prop.desktop_file)
11444           {
11445              const char *desktop = bd->remember->prop.desktop_file;
11446
11447              bd->desktop = efreet_desktop_get(desktop);
11448              if (!bd->desktop)
11449                bd->desktop = efreet_util_desktop_name_find(desktop);
11450           }
11451         if (!bd->desktop)
11452           {
11453              if ((bd->client.icccm.name) && (bd->client.icccm.class))
11454                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
11455                                                                bd->client.icccm.class);
11456           }
11457         if (!bd->desktop)
11458           {
11459              /* libreoffice and maybe others match window class
11460                 with .desktop file name */
11461              if (bd->client.icccm.class)
11462                {
11463                   char buf[128];
11464                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
11465                   bd->desktop = efreet_util_desktop_file_id_find(buf);
11466                }
11467           }
11468         if (!bd->desktop)
11469           {
11470              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
11471                                                       bd->client.netwm.pid);
11472              if (bd->desktop) efreet_desktop_ref(bd->desktop);
11473           }
11474         if (!bd->desktop && bd->client.icccm.name)
11475           {
11476              /* this works for most cases as fallback. useful when app is
11477                 run from a shell  */
11478              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
11479           }
11480         if (!bd->desktop && bd->client.icccm.transient_for)
11481           {
11482              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
11483              if (bd2 && bd2->desktop)
11484                {
11485                   efreet_desktop_ref(bd2->desktop);
11486                   bd->desktop = bd2->desktop;
11487                }
11488           }
11489         if (bd->desktop)
11490           {
11491              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
11492                                             bd->desktop->orig_path);
11493           }
11494
11495         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
11496         if ((bd->focused) && (bd->icon_object))
11497           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
11498         if (bd->bg_object)
11499           {
11500              evas_object_show(bd->icon_object);
11501              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
11502           }
11503         else
11504           evas_object_hide(bd->icon_object);
11505
11506         {
11507            E_Event_Border_Icon_Change *ev;
11508
11509            ev = E_NEW(E_Event_Border_Icon_Change, 1);
11510            ev->border = bd;
11511            e_object_ref(E_OBJECT(bd));
11512            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
11513            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
11514                            _e_border_event_border_icon_change_free, NULL);
11515         }
11516         bd->changes.icon = 0;
11517      }
11518
11519    bd->new_client = 0;
11520    bd->changed = 0;
11521    bd->changes.stack = 0;
11522    bd->changes.prop = 0;
11523
11524    if (bd->client.e.state.rot.changes != -1)
11525      {
11526         e_border_rotation_set(bd, bd->client.e.state.rot.changes);
11527         bd->client.e.state.rot.changes = -1;
11528      }
11529
11530    if ((bd->take_focus) || (bd->want_focus))
11531      {
11532         bd->take_focus = 0;
11533 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11534         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
11535             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
11536             (bd->want_focus))
11537 #else // original
11538         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
11539 #endif
11540           {
11541              bd->want_focus = 0;
11542 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11543              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
11544                 _e_border_check_stack(bd);
11545              else
11546 #endif
11547              e_border_focus_set_with_pointer(bd);
11548           }
11549         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11550           {
11551              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
11552                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
11553                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
11554                    e_border_focused_get())))
11555                {
11556                   e_border_focus_set_with_pointer(bd);
11557                }
11558           }
11559         else
11560           {
11561              /* focus window by default when it is the only one on desk */
11562              E_Border *bd2 = NULL;
11563              Eina_List *l;
11564              EINA_LIST_FOREACH(focus_stack, l, bd2)
11565                {
11566                   if (bd == bd2) continue;
11567                   if ((!bd2->iconic) && (bd2->visible) &&
11568                       ((bd->desk == bd2->desk) || bd2->sticky))
11569                     break;
11570                }
11571
11572              if (!bd2)
11573                {
11574                   e_border_focus_set_with_pointer(bd);
11575                }
11576           }
11577      }
11578
11579    if (bd->need_maximize)
11580      {
11581         E_Maximize max;
11582         max = bd->maximized;
11583         bd->maximized = E_MAXIMIZE_NONE;
11584         e_border_maximize(bd, max);
11585         bd->need_maximize = 0;
11586      }
11587
11588    if (bd->need_fullscreen)
11589      {
11590         e_border_fullscreen(bd, e_config->fullscreen_policy);
11591         bd->need_fullscreen = 0;
11592      }
11593
11594    if (rem_change)
11595      e_remember_update(bd);
11596
11597    if (send_event) // FIXME: send only if a property changed - above need to
11598      { // check on that. for now - always send.
11599         event = E_NEW(E_Event_Border_Property, 1);
11600         event->border = bd;
11601         e_object_ref(E_OBJECT(bd));
11602         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11603      }
11604    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11605 }
11606
11607 static void
11608 _e_border_moveinfo_gather(E_Border   *bd,
11609                           const char *source)
11610 {
11611    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11612    else if (e_util_glob_match(source, "mouse,*,2"))
11613      bd->moveinfo.down.button = 2;
11614    else if (e_util_glob_match(source, "mouse,*,3"))
11615      bd->moveinfo.down.button = 3;
11616    else bd->moveinfo.down.button = 0;
11617    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11618      {
11619         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11620         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11621      }
11622    else
11623      {
11624         bd->moveinfo.down.mx = bd->mouse.current.mx;
11625         bd->moveinfo.down.my = bd->mouse.current.my;
11626      }
11627 }
11628
11629 static void
11630 _e_border_resize_handle(E_Border *bd)
11631 {
11632    int x, y, w, h;
11633    int new_x, new_y, new_w, new_h;
11634    int tw, th;
11635    Eina_List *skiplist = NULL;
11636
11637    x = bd->x;
11638    y = bd->y;
11639    w = bd->w;
11640    h = bd->h;
11641
11642    if ((bd->resize_mode == RESIZE_TR) ||
11643        (bd->resize_mode == RESIZE_R) ||
11644        (bd->resize_mode == RESIZE_BR))
11645      {
11646         if ((bd->moveinfo.down.button >= 1) &&
11647             (bd->moveinfo.down.button <= 3))
11648           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11649             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11650         else
11651           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11652      }
11653    else if ((bd->resize_mode == RESIZE_TL) ||
11654             (bd->resize_mode == RESIZE_L) ||
11655             (bd->resize_mode == RESIZE_BL))
11656      {
11657         if ((bd->moveinfo.down.button >= 1) &&
11658             (bd->moveinfo.down.button <= 3))
11659           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11660             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11661         else
11662           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11663      }
11664
11665    if ((bd->resize_mode == RESIZE_TL) ||
11666        (bd->resize_mode == RESIZE_T) ||
11667        (bd->resize_mode == RESIZE_TR))
11668      {
11669         if ((bd->moveinfo.down.button >= 1) &&
11670             (bd->moveinfo.down.button <= 3))
11671           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11672             (bd->mouse.current.my - bd->moveinfo.down.my);
11673         else
11674           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11675      }
11676    else if ((bd->resize_mode == RESIZE_BL) ||
11677             (bd->resize_mode == RESIZE_B) ||
11678             (bd->resize_mode == RESIZE_BR))
11679      {
11680         if ((bd->moveinfo.down.button >= 1) &&
11681             (bd->moveinfo.down.button <= 3))
11682           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11683             (bd->mouse.current.my - bd->moveinfo.down.my);
11684         else
11685           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11686      }
11687
11688    tw = bd->w;
11689    th = bd->h;
11690
11691    if ((bd->resize_mode == RESIZE_TL) ||
11692        (bd->resize_mode == RESIZE_L) ||
11693        (bd->resize_mode == RESIZE_BL))
11694      x += (tw - w);
11695    if ((bd->resize_mode == RESIZE_TL) ||
11696        (bd->resize_mode == RESIZE_T) ||
11697        (bd->resize_mode == RESIZE_TR))
11698      y += (th - h);
11699
11700    skiplist = eina_list_append(skiplist, bd);
11701    e_resist_container_border_position(bd->zone->container, skiplist,
11702                                       bd->x, bd->y, bd->w, bd->h,
11703                                       x, y, w, h,
11704                                       &new_x, &new_y, &new_w, &new_h);
11705    eina_list_free(skiplist);
11706
11707    w = new_w;
11708    h = new_h;
11709    e_border_resize_limit(bd, &new_w, &new_h);
11710    if ((bd->resize_mode == RESIZE_TL) ||
11711        (bd->resize_mode == RESIZE_L) ||
11712        (bd->resize_mode == RESIZE_BL))
11713      new_x += (w - new_w);
11714    if ((bd->resize_mode == RESIZE_TL) ||
11715        (bd->resize_mode == RESIZE_T) ||
11716        (bd->resize_mode == RESIZE_TR))
11717      new_y += (h - new_h);
11718
11719    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11720 }
11721
11722 static Eina_Bool
11723 _e_border_shade_animator(void *data)
11724 {
11725    E_Border *bd = data;
11726    double dt, val;
11727    double dur = bd->client.h / e_config->border_shade_speed;
11728
11729    dt = ecore_loop_time_get() - bd->shade.start;
11730    val = dt / dur;
11731
11732    if (val < 0.0) val = 0.0;
11733    else if (val > 1.0) val = 1.0;
11734
11735    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11736      {
11737         bd->shade.val =
11738            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
11739         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11740      }
11741    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
11742      {
11743         bd->shade.val =
11744            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
11745         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11746      }
11747    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
11748      {
11749         bd->shade.val =
11750            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
11751         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11752      }
11753    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
11754      {
11755         bd->shade.val =
11756            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11757         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11758      }
11759    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
11760      {
11761         bd->shade.val =
11762            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
11763         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11764      }
11765    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
11766      {
11767         bd->shade.val =
11768            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
11769         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11770      }
11771    else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
11772      {
11773         bd->shade.val =
11774            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.0);
11775         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11776      }
11777    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE)
11778      {
11779         bd->shade.val =
11780            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
11781         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11782      }
11783    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
11784      {
11785         bd->shade.val =
11786            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
11787         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11788      }
11789    else
11790      {
11791         bd->shade.val =
11792            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11793         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11794      }
11795
11796    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
11797    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
11798    else if (bd->shade.val > .999)
11799      bd->shade.val = 1.0;
11800
11801    if (bd->shade.dir == E_DIRECTION_UP)
11802      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11803    else if (bd->shade.dir == E_DIRECTION_DOWN)
11804      {
11805         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11806         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
11807         bd->changes.pos = 1;
11808      }
11809    else if (bd->shade.dir == E_DIRECTION_LEFT)
11810      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11811    else if (bd->shade.dir == E_DIRECTION_RIGHT)
11812      {
11813         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11814         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
11815         bd->changes.pos = 1;
11816      }
11817
11818    if ((bd->shaped) || (bd->client.shaped))
11819      {
11820         bd->need_shape_merge = 1;
11821         bd->need_shape_export = 1;
11822      }
11823    if (bd->shaped_input)
11824      {
11825         bd->need_shape_merge = 1;
11826      }
11827    bd->changes.size = 1;
11828    bd->changed = 1;
11829
11830    /* we're done */
11831    if (val == 1)
11832      {
11833         E_Event_Border_Resize *ev;
11834
11835         bd->shading = 0;
11836         bd->shaded = !(bd->shaded);
11837         bd->changes.size = 1;
11838         bd->changes.shaded = 1;
11839         bd->changes.shading = 1;
11840         bd->changed = 1;
11841         bd->shade.anim = NULL;
11842
11843         if (bd->shaded)
11844           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
11845         else
11846           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
11847         edje_object_message_signal_process(bd->bg_object);
11848         e_border_frame_recalc(bd);
11849
11850         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
11851         ev = E_NEW(E_Event_Border_Resize, 1);
11852         ev->border = bd;
11853         e_object_ref(E_OBJECT(bd));
11854 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
11855         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
11856         return ECORE_CALLBACK_CANCEL;
11857      }
11858    return ECORE_CALLBACK_RENEW;
11859 }
11860
11861 static void
11862 _e_border_event_border_resize_free(void *data __UNUSED__,
11863                                    void      *ev)
11864 {
11865    E_Event_Border_Resize *e;
11866
11867    e = ev;
11868 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
11869    e_object_unref(E_OBJECT(e->border));
11870    E_FREE(e);
11871 }
11872
11873 static void
11874 _e_border_event_border_move_free(void *data __UNUSED__,
11875                                  void      *ev)
11876 {
11877    E_Event_Border_Move *e;
11878
11879    e = ev;
11880 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
11881    e_object_unref(E_OBJECT(e->border));
11882    E_FREE(e);
11883 }
11884
11885 static void
11886 _e_border_event_border_add_free(void *data __UNUSED__,
11887                                 void      *ev)
11888 {
11889    E_Event_Border_Add *e;
11890
11891    e = ev;
11892 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
11893    e_object_unref(E_OBJECT(e->border));
11894    E_FREE(e);
11895 }
11896
11897 static void
11898 _e_border_event_border_remove_free(void *data __UNUSED__,
11899                                    void      *ev)
11900 {
11901    E_Event_Border_Remove *e;
11902
11903    e = ev;
11904 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
11905    e_object_unref(E_OBJECT(e->border));
11906    E_FREE(e);
11907 }
11908
11909 static void
11910 _e_border_event_border_show_free(void *data __UNUSED__,
11911                                  void      *ev)
11912 {
11913    E_Event_Border_Show *e;
11914
11915    e = ev;
11916 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
11917    e_object_unref(E_OBJECT(e->border));
11918    E_FREE(e);
11919 }
11920
11921 static void
11922 _e_border_event_border_hide_free(void *data __UNUSED__,
11923                                  void      *ev)
11924 {
11925    E_Event_Border_Hide *e;
11926
11927    e = ev;
11928 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
11929    e_object_unref(E_OBJECT(e->border));
11930    E_FREE(e);
11931 }
11932
11933 static void
11934 _e_border_event_border_iconify_free(void *data __UNUSED__,
11935                                     void      *ev)
11936 {
11937    E_Event_Border_Iconify *e;
11938
11939    e = ev;
11940 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
11941    e_object_unref(E_OBJECT(e->border));
11942    E_FREE(e);
11943 }
11944
11945 static void
11946 _e_border_event_border_uniconify_free(void *data __UNUSED__,
11947                                       void      *ev)
11948 {
11949    E_Event_Border_Uniconify *e;
11950
11951    e = ev;
11952 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
11953    e_object_unref(E_OBJECT(e->border));
11954    E_FREE(e);
11955 }
11956
11957 static void
11958 _e_border_event_border_stick_free(void *data __UNUSED__,
11959                                   void      *ev)
11960 {
11961    E_Event_Border_Stick *e;
11962
11963    e = ev;
11964 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
11965    e_object_unref(E_OBJECT(e->border));
11966    E_FREE(e);
11967 }
11968
11969 static void
11970 _e_border_event_border_unstick_free(void *data __UNUSED__,
11971                                     void      *ev)
11972 {
11973    E_Event_Border_Unstick *e;
11974
11975    e = ev;
11976 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
11977    e_object_unref(E_OBJECT(e->border));
11978    E_FREE(e);
11979 }
11980
11981 static void
11982 _e_border_event_border_zone_set_free(void *data __UNUSED__,
11983                                      void      *ev)
11984 {
11985    E_Event_Border_Zone_Set *e;
11986
11987    e = ev;
11988 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
11989    e_object_unref(E_OBJECT(e->border));
11990    e_object_unref(E_OBJECT(e->zone));
11991    E_FREE(e);
11992 }
11993
11994 static void
11995 _e_border_event_border_desk_set_free(void *data __UNUSED__,
11996                                      void      *ev)
11997 {
11998    E_Event_Border_Desk_Set *e;
11999
12000    e = ev;
12001 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
12002    e_object_unref(E_OBJECT(e->border));
12003    e_object_unref(E_OBJECT(e->desk));
12004    E_FREE(e);
12005 }
12006
12007 static void
12008 _e_border_event_border_stack_free(void *data __UNUSED__,
12009                                   void      *ev)
12010 {
12011    E_Event_Border_Stack *e;
12012
12013    e = ev;
12014 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
12015    e_object_unref(E_OBJECT(e->border));
12016    if (e->stack)
12017      {
12018 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
12019           e_object_unref(E_OBJECT(e->stack));
12020      }
12021    E_FREE(e);
12022 }
12023
12024 static void
12025 _e_border_event_border_icon_change_free(void *data __UNUSED__,
12026                                         void      *ev)
12027 {
12028    E_Event_Border_Icon_Change *e;
12029
12030    e = ev;
12031 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
12032    e_object_unref(E_OBJECT(e->border));
12033    E_FREE(e);
12034 }
12035
12036 static void
12037 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
12038                                           void      *ev)
12039 {
12040    E_Event_Border_Urgent_Change *e;
12041
12042    e = ev;
12043    e_object_unref(E_OBJECT(e->border));
12044    E_FREE(e);
12045 }
12046
12047 static void
12048 _e_border_event_border_focus_in_free(void *data __UNUSED__,
12049                                      void      *ev)
12050 {
12051    E_Event_Border_Focus_In *e;
12052
12053    e = ev;
12054    e_object_unref(E_OBJECT(e->border));
12055    E_FREE(e);
12056 }
12057
12058 static void
12059 _e_border_event_border_focus_out_free(void *data __UNUSED__,
12060                                       void      *ev)
12061 {
12062    E_Event_Border_Focus_Out *e;
12063
12064    e = ev;
12065    e_object_unref(E_OBJECT(e->border));
12066    E_FREE(e);
12067 }
12068
12069 static void
12070 _e_border_event_border_property_free(void *data __UNUSED__,
12071                                      void      *ev)
12072 {
12073    E_Event_Border_Property *e;
12074
12075    e = ev;
12076    e_object_unref(E_OBJECT(e->border));
12077    E_FREE(e);
12078 }
12079
12080 static void
12081 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
12082                                        void      *ev)
12083 {
12084    E_Event_Border_Fullscreen *e;
12085
12086    e = ev;
12087 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
12088    e_object_unref(E_OBJECT(e->border));
12089    E_FREE(e);
12090 }
12091
12092 static void
12093 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
12094                                          void      *ev)
12095 {
12096    E_Event_Border_Unfullscreen *e;
12097
12098    e = ev;
12099 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
12100    e_object_unref(E_OBJECT(e->border));
12101    E_FREE(e);
12102 }
12103
12104 #ifdef _F_ZONE_WINDOW_ROTATION_
12105 static void
12106 _e_border_event_border_rotation_change_begin_free(void *data __UNUSED__,
12107                                                   void      *ev)
12108 {
12109    E_Event_Border_Rotation_Change_Begin *e;
12110    e = ev;
12111    e_object_unref(E_OBJECT(e->border));
12112    E_FREE(e);
12113 }
12114
12115 static void
12116 _e_border_event_border_rotation_change_cancel_free(void *data __UNUSED__,
12117                                                    void      *ev)
12118 {
12119    E_Event_Border_Rotation_Change_Cancel *e;
12120    e = ev;
12121    e_object_unref(E_OBJECT(e->border));
12122    E_FREE(e);
12123 }
12124
12125 static void
12126 _e_border_event_border_rotation_change_end_free(void *data __UNUSED__,
12127                                                 void      *ev)
12128 {
12129    E_Event_Border_Rotation_Change_End *e;
12130    e = ev;
12131    e_object_unref(E_OBJECT(e->border));
12132    E_FREE(e);
12133 }
12134
12135 static void
12136 _e_border_event_border_rotation_change_begin_send(E_Border *bd)
12137 {
12138    E_Event_Border_Rotation_Change_Begin *ev = NULL;
12139    ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
12140    if (ev)
12141      {
12142         ev->border = bd;
12143         e_object_ref(E_OBJECT(bd));
12144         ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_BEGIN,
12145                         ev,
12146                         _e_border_event_border_rotation_change_begin_free,
12147                         NULL);
12148      }
12149 }
12150 #endif
12151
12152 static void
12153 _e_border_zone_update(E_Border *bd)
12154 {
12155    E_Container *con;
12156    Eina_List *l;
12157    E_Zone *zone;
12158
12159    /* still within old zone - leave it there */
12160    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12161                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
12162 #if _F_BORDER_CLIP_TO_ZONE_
12163      {
12164         _e_border_shape_input_clip_to_zone(bd);
12165         return;
12166      }
12167 #else
12168      return;
12169 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12170    /* find a new zone */
12171    con = bd->zone->container;
12172    EINA_LIST_FOREACH(con->zones, l, zone)
12173      {
12174         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12175                          zone->x, zone->y, zone->w, zone->h))
12176           {
12177              e_border_zone_set(bd, zone);
12178 #if _F_BORDER_CLIP_TO_ZONE_
12179              _e_border_shape_input_clip_to_zone(bd);
12180 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12181              return;
12182           }
12183      }
12184 }
12185
12186 static int
12187 _e_border_resize_begin(E_Border *bd)
12188 {
12189    int ret;
12190
12191    if (!bd->lock_user_stacking)
12192      {
12193         if (e_config->border_raise_on_mouse_action)
12194           e_border_raise(bd);
12195      }
12196    if ((bd->shaded) || (bd->shading) ||
12197        (bd->fullscreen) || (bd->lock_user_size))
12198      return 0;
12199
12200    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12201      ret = e_grabinput_get(bd->win, 0, bd->win);
12202    else
12203      ret = e_grabinput_get(bd->win, 0, 0);
12204
12205    if (grabbed && !ret)
12206      {
12207         grabbed = 0;
12208         return 0;
12209      }
12210
12211    if (bd->client.netwm.sync.request)
12212      {
12213         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12214         bd->client.netwm.sync.serial = 1;
12215         bd->client.netwm.sync.wait = 0;
12216         bd->client.netwm.sync.send_time = ecore_loop_time_get();
12217      }
12218
12219    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
12220
12221    bdresize = bd;
12222    return 1;
12223 }
12224
12225 static int
12226 _e_border_resize_end(E_Border *bd)
12227 {
12228    if (grabbed)
12229      {
12230         e_grabinput_release(bd->win, bd->win);
12231         grabbed = 0;
12232      }
12233    if (bd->client.netwm.sync.alarm)
12234      {
12235         E_Border_Pending_Move_Resize *pnd;
12236
12237         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12238         bd->client.netwm.sync.alarm = 0;
12239         /* resize to last geometry if sync alarm for it was not yet handled */
12240         if (bd->pending_move_resize)
12241           {
12242              bd->changed = 1;
12243              bd->changes.pos = 1;
12244              bd->changes.size = 1;
12245              _e_border_client_move_resize_send(bd);
12246           }
12247
12248         EINA_LIST_FREE(bd->pending_move_resize, pnd)
12249           E_FREE(pnd);
12250      }
12251
12252    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
12253
12254    bdresize = NULL;
12255
12256    /* If this border was maximized, we need to unset Maximized state or
12257     * on restart, E still thinks it's maximized */
12258    if (bd->maximized != E_MAXIMIZE_NONE)
12259      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
12260                                   bd->maximized & E_MAXIMIZE_NONE);
12261    return 1;
12262 }
12263
12264 static void
12265 _e_border_resize_update(E_Border *bd)
12266 {
12267    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
12268 }
12269
12270 static int
12271 _e_border_move_begin(E_Border *bd)
12272 {
12273    int ret;
12274    if (!bd->lock_user_stacking)
12275      {
12276         if (e_config->border_raise_on_mouse_action)
12277           e_border_raise(bd);
12278      }
12279    if ((bd->fullscreen) || (bd->lock_user_location))
12280      return 0;
12281
12282    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12283      ret = e_grabinput_get(bd->win, 0, bd->win);
12284    else
12285      ret = e_grabinput_get(bd->win, 0, 0);
12286
12287    if (grabbed && !ret)
12288      {
12289         grabbed = 0;
12290         return 0;
12291      }
12292 #if 0
12293    if (bd->client.netwm.sync.request)
12294      {
12295         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12296         bd->client.netwm.sync.serial = 0;
12297         bd->client.netwm.sync.wait = 0;
12298         bd->client.netwm.sync.time = ecore_loop_time_get();
12299      }
12300 #endif
12301    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
12302
12303    bdmove = bd;
12304    return 1;
12305 }
12306
12307 static int
12308 _e_border_move_end(E_Border *bd)
12309 {
12310    if (grabbed)
12311      {
12312         e_grabinput_release(bd->win, bd->win);
12313         grabbed = 0;
12314      }
12315 #if 0
12316    if (bd->client.netwm.sync.alarm)
12317      {
12318         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12319         bd->client.netwm.sync.alarm = 0;
12320      }
12321 #endif
12322    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
12323
12324    bdmove = NULL;
12325    return 1;
12326 }
12327
12328 static void
12329 _e_border_move_update(E_Border *bd)
12330 {
12331    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
12332 }
12333
12334 static Eina_Bool
12335 _e_border_cb_ping_poller(void *data)
12336 {
12337    E_Border *bd;
12338
12339    bd = data;
12340    if (bd->ping_ok)
12341      {
12342         if (bd->hung)
12343           {
12344              bd->hung = 0;
12345              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
12346              if (bd->kill_timer)
12347                {
12348                   ecore_timer_del(bd->kill_timer);
12349                   bd->kill_timer = NULL;
12350                }
12351           }
12352      }
12353    else
12354      {
12355         /* if time between last ping and now is greater
12356          * than half the ping interval... */
12357         if ((ecore_loop_time_get() - bd->ping) >
12358             ((e_config->ping_clients_interval *
12359               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
12360           {
12361              if (!bd->hung)
12362                {
12363                   bd->hung = 1;
12364                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
12365                   /* FIXME: if below dialog is up - hide it now */
12366                }
12367              if (bd->delete_requested)
12368                {
12369                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
12370                   e_border_act_kill_begin(bd);
12371                }
12372           }
12373      }
12374    bd->ping_poller = NULL;
12375    e_border_ping(bd);
12376    return ECORE_CALLBACK_CANCEL;
12377 }
12378
12379 static Eina_Bool
12380 _e_border_cb_kill_timer(void *data)
12381 {
12382    E_Border *bd;
12383
12384    bd = data;
12385 // dont wait until it's hung -
12386 //   if (bd->hung)
12387 //     {
12388         if (bd->client.netwm.pid > 1)
12389           kill(bd->client.netwm.pid, SIGKILL);
12390 //     }
12391    bd->kill_timer = NULL;
12392    return ECORE_CALLBACK_CANCEL;
12393 }
12394
12395 static void
12396 _e_border_pointer_resize_begin(E_Border *bd)
12397 {
12398    switch (bd->resize_mode)
12399      {
12400       case RESIZE_TL:
12401         e_pointer_type_push(bd->pointer, bd, "resize_tl");
12402         break;
12403
12404       case RESIZE_T:
12405         e_pointer_type_push(bd->pointer, bd, "resize_t");
12406         break;
12407
12408       case RESIZE_TR:
12409         e_pointer_type_push(bd->pointer, bd, "resize_tr");
12410         break;
12411
12412       case RESIZE_R:
12413         e_pointer_type_push(bd->pointer, bd, "resize_r");
12414         break;
12415
12416       case RESIZE_BR:
12417         e_pointer_type_push(bd->pointer, bd, "resize_br");
12418         break;
12419
12420       case RESIZE_B:
12421         e_pointer_type_push(bd->pointer, bd, "resize_b");
12422         break;
12423
12424       case RESIZE_BL:
12425         e_pointer_type_push(bd->pointer, bd, "resize_bl");
12426         break;
12427
12428       case RESIZE_L:
12429         e_pointer_type_push(bd->pointer, bd, "resize_l");
12430         break;
12431      }
12432 }
12433
12434 static void
12435 _e_border_pointer_resize_end(E_Border *bd)
12436 {
12437    switch (bd->resize_mode)
12438      {
12439       case RESIZE_TL:
12440         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
12441         break;
12442
12443       case RESIZE_T:
12444         e_pointer_type_pop(bd->pointer, bd, "resize_t");
12445         break;
12446
12447       case RESIZE_TR:
12448         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
12449         break;
12450
12451       case RESIZE_R:
12452         e_pointer_type_pop(bd->pointer, bd, "resize_r");
12453         break;
12454
12455       case RESIZE_BR:
12456         e_pointer_type_pop(bd->pointer, bd, "resize_br");
12457         break;
12458
12459       case RESIZE_B:
12460         e_pointer_type_pop(bd->pointer, bd, "resize_b");
12461         break;
12462
12463       case RESIZE_BL:
12464         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
12465         break;
12466
12467       case RESIZE_L:
12468         e_pointer_type_pop(bd->pointer, bd, "resize_l");
12469         break;
12470      }
12471 }
12472
12473 static void
12474 _e_border_pointer_move_begin(E_Border *bd)
12475 {
12476    e_pointer_type_push(bd->pointer, bd, "move");
12477 }
12478
12479 static void
12480 _e_border_pointer_move_end(E_Border *bd)
12481 {
12482    e_pointer_type_pop(bd->pointer, bd, "move");
12483 }
12484
12485 static Eina_List *_e_border_hooks = NULL;
12486 static int _e_border_hooks_delete = 0;
12487 static int _e_border_hooks_walking = 0;
12488
12489 static void
12490 _e_border_hooks_clean(void)
12491 {
12492    Eina_List *l, *ln;
12493    E_Border_Hook *bh;
12494
12495    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
12496      {
12497         if (bh->delete_me)
12498           {
12499              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
12500              free(bh);
12501           }
12502      }
12503 }
12504
12505 static void
12506 _e_border_hook_call(E_Border_Hook_Point hookpoint,
12507                     void               *bd)
12508 {
12509    Eina_List *l;
12510    E_Border_Hook *bh;
12511
12512    _e_border_hooks_walking++;
12513    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
12514      {
12515         if (bh->delete_me) continue;
12516         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
12517      }
12518    _e_border_hooks_walking--;
12519    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
12520      _e_border_hooks_clean();
12521 }
12522
12523 EAPI E_Border_Hook *
12524 e_border_hook_add(E_Border_Hook_Point               hookpoint,
12525                   void                              (*func)(void *data,
12526                                               void *bd),
12527                   void                             *data)
12528 {
12529    E_Border_Hook *bh;
12530
12531    bh = E_NEW(E_Border_Hook, 1);
12532    if (!bh) return NULL;
12533    bh->hookpoint = hookpoint;
12534    bh->func = func;
12535    bh->data = data;
12536    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
12537    return bh;
12538 }
12539
12540 EAPI void
12541 e_border_hook_del(E_Border_Hook *bh)
12542 {
12543    bh->delete_me = 1;
12544    if (_e_border_hooks_walking == 0)
12545      {
12546         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
12547         free(bh);
12548      }
12549    else
12550      _e_border_hooks_delete++;
12551 }
12552
12553 EAPI void
12554 e_border_focus_track_freeze(void)
12555 {
12556    focus_track_frozen++;
12557 }
12558
12559 EAPI void
12560 e_border_focus_track_thaw(void)
12561 {
12562    focus_track_frozen--;
12563 }
12564
12565 EAPI E_Border *
12566 e_border_under_pointer_get(E_Desk   *desk,
12567                            E_Border *exclude)
12568 {
12569    E_Border *bd = NULL, *cbd;
12570    Eina_List *l;
12571    int x, y;
12572
12573    /* We need to ensure that we can get the container window for the
12574     * zone of either the given desk or the desk of the excluded
12575     * window, so return if neither is given */
12576    if (desk)
12577      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
12578    else if (exclude)
12579      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
12580    else
12581      return NULL;
12582
12583    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
12584      {
12585         if (!cbd) continue;
12586         /* If a border was specified which should be excluded from the list
12587          * (because it will be closed shortly for example), skip */
12588         if ((exclude) && (cbd == exclude)) continue;
12589         if ((desk) && (cbd->desk != desk)) continue;
12590         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
12591           continue;
12592         /* If the layer is higher, the position of the window is higher
12593          * (always on top vs always below) */
12594         if (!bd || (cbd->layer > bd->layer))
12595           {
12596              bd = cbd;
12597              break;
12598           }
12599      }
12600    return bd;
12601 }
12602
12603 static Eina_Bool
12604 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
12605 {
12606    if (warp_to)
12607      {
12608         int x, y;
12609         double spd;
12610
12611         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
12612         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
12613             (y - warp_y) > 5 || (y - warp_y) < -5)
12614           {
12615              /* User moved the mouse, so stop warping */
12616              warp_to = 0;
12617              goto cleanup;
12618           }
12619
12620         /* We just use the same warp speed as configured
12621          * for the windowlist */
12622         spd = e_config->winlist_warp_speed;
12623         x = warp_x;
12624         y = warp_y;
12625         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12626         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12627         if (warp_x == x && warp_y == y)
12628           {
12629              warp_x = warp_to_x;
12630              warp_y = warp_to_y;
12631              warp_to = 0;
12632              goto cleanup;
12633           }
12634         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12635         return ECORE_CALLBACK_RENEW;
12636      }
12637  cleanup:
12638    ecore_timer_del(warp_timer);
12639    warp_timer = NULL;
12640    return ECORE_CALLBACK_CANCEL;
12641 }
12642
12643 EAPI int
12644 e_border_pointer_warp_to_center(E_Border *bd)
12645 {
12646    int x, y;
12647
12648    /* Do not slide pointer when disabled (probably breaks focus
12649     * on sloppy/mouse focus but requested by users). */
12650    if (!e_config->pointer_slide) return 0;
12651    /* Only warp the pointer if it is not already in the area of
12652     * the given border */
12653    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12654    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12655        (y >= bd->y) && (y <= (bd->y + bd->h)))
12656      return 0;
12657
12658    warp_to_x = bd->x + (bd->w / 2);
12659    if (warp_to_x < (bd->zone->x + 1))
12660      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12661    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12662      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12663
12664    warp_to_y = bd->y + (bd->h / 2);
12665    if (warp_to_y < (bd->zone->y + 1))
12666      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12667    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12668      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12669
12670    warp_to = 1;
12671    warp_to_win = bd->zone->container->win;
12672    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12673    if (!warp_timer)
12674      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12675    return 1;
12676 }
12677
12678 EAPI void
12679 e_border_comp_hidden_set(E_Border *bd,
12680                          Eina_Bool hidden)
12681 {
12682    E_Border *tmp;
12683    Eina_List *l;
12684
12685    E_OBJECT_CHECK(bd);
12686    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12687
12688    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12689      {
12690        if (hidden)
12691          ecore_x_window_hide(tmp->win);
12692        else
12693          ecore_x_window_show(tmp->win);
12694      }
12695
12696    if (bd->comp_hidden == hidden) return;
12697
12698    bd->comp_hidden = hidden;
12699
12700    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12701      {
12702         ecore_x_composite_window_events_disable(bd->win);
12703         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12704      }
12705    else
12706      {
12707         _e_border_shape_input_rectangle_set(bd);
12708         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12709      }
12710 }
12711
12712 EAPI void
12713 e_border_tmp_input_hidden_push(E_Border *bd)
12714 {
12715    E_Border *tmp;
12716    Eina_List *l;
12717
12718    E_OBJECT_CHECK(bd);
12719    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12720
12721    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12722      e_border_tmp_input_hidden_push(tmp);
12723
12724    bd->tmp_input_hidden++;
12725    if (bd->tmp_input_hidden != 1) return;
12726
12727    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12728      {
12729         ecore_x_composite_window_events_disable(bd->win);
12730         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12731      }
12732    else
12733      {
12734         _e_border_shape_input_rectangle_set(bd);
12735         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12736      }
12737 }
12738
12739 EAPI void
12740 e_border_tmp_input_hidden_pop(E_Border *bd)
12741 {
12742    E_Border *tmp;
12743    Eina_List *l;
12744
12745    E_OBJECT_CHECK(bd);
12746    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12747
12748    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12749      e_border_tmp_input_hidden_pop(tmp);
12750
12751    bd->tmp_input_hidden--;
12752    if (bd->tmp_input_hidden != 0) return;
12753
12754    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12755      {
12756         ecore_x_composite_window_events_disable(bd->win);
12757         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12758      }
12759    else
12760      {
12761         _e_border_shape_input_rectangle_set(bd);
12762         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12763      }
12764 }
12765
12766 EAPI void
12767 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
12768 {
12769    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
12770        ((bd->parent) &&
12771         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
12772          ((bd->parent->focused) &&
12773           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
12774        (just_do_it))
12775      {
12776         if (bd->iconic)
12777           {
12778              if (e_config->clientlist_warp_to_iconified_desktop == 1)
12779                e_desk_show(bd->desk);
12780              
12781              if (!bd->lock_user_iconify)
12782                e_border_uniconify(bd);
12783           }
12784         if ((!bd->iconic) && (!bd->sticky))
12785           e_desk_show(bd->desk);
12786         if (!bd->lock_user_stacking) e_border_raise(bd);
12787         if (!bd->lock_focus_out)
12788           {
12789              /* XXX ooffice does send this request for
12790               config dialogs when the main window gets focus.
12791               causing the pointer to jump back and forth.  */
12792              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
12793                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
12794                ecore_x_pointer_warp(bd->zone->container->win,
12795                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
12796              e_border_focus_set(bd, 1, 1);
12797           }
12798      }
12799 }
12800 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/