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