To support such as quickpanel to rotate based Window manager,
[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);
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    Ecore_X_Event_Window_Show_Request *e;
5864
5865    e = ev;
5866    bd = e_border_find_by_client_window(e->win);
5867    if (!bd) return ECORE_CALLBACK_PASS_ON;
5868    if (bd->iconic)
5869      {
5870         if (!bd->lock_client_iconify)
5871           e_border_uniconify(bd);
5872      }
5873    else
5874      {
5875         /* FIXME: make border "urgent" for a bit - it wants attention */
5876 /*      e_border_show(bd); */
5877           if (!bd->lock_client_stacking)
5878             e_border_raise(bd);
5879      }
5880    return ECORE_CALLBACK_PASS_ON;
5881 }
5882
5883 static Eina_Bool
5884 _e_border_cb_window_destroy(void *data  __UNUSED__,
5885                             int ev_type __UNUSED__,
5886                             void       *ev)
5887 {
5888    E_Border *bd;
5889    Ecore_X_Event_Window_Destroy *e;
5890
5891    e = ev;
5892    bd = e_border_find_by_client_window(e->win);
5893    if (!bd) return ECORE_CALLBACK_PASS_ON;
5894    ELB(ELBT_BD, "X_WIN_DEL", bd->client.win);
5895 #ifdef _F_ZONE_WINDOW_ROTATION_
5896    if (e_config->wm_win_rotation)
5897      {
5898         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
5899           {
5900              ELB(ELBT_BD, "X_DEL_NOTIFY", bd->client.win);
5901              if (!rot.vkbd_hide_prepare_timer)
5902                {
5903                   ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
5904                   e_border_hide(bd, 0);
5905                   if (!rot.vkbd_hide_prepare_timer)
5906                     {
5907                        ELB(ELBT_BD, "DEL VKBD", bd->client.win);
5908                        e_object_del(E_OBJECT(bd));
5909                     }
5910                }
5911              return ECORE_CALLBACK_PASS_ON;
5912           }
5913      }
5914 #endif
5915    e_border_hide(bd, 0);
5916    e_object_del(E_OBJECT(bd));
5917    return ECORE_CALLBACK_PASS_ON;
5918 }
5919
5920 static Eina_Bool
5921 _e_border_cb_window_hide(void *data  __UNUSED__,
5922                          int ev_type __UNUSED__,
5923                          void       *ev)
5924 {
5925    E_Border *bd = NULL;
5926    Ecore_X_Event_Window_Hide *e;
5927
5928    e = ev;
5929 //   printf("HIDE: %x, event %x send: %i\n", e->win, e->event_win, e->send_event);
5930 // not interested in hide events from windows other than the window in question
5931    if (e->win != e->event_win)
5932      {
5933         bd = e_border_find_by_client_window(e->win);
5934         if (!bd) return ECORE_CALLBACK_PASS_ON;
5935         if (!e->send_event) return ECORE_CALLBACK_PASS_ON;
5936         else
5937           {
5938              if (!((bd->zone) &&
5939                    (bd->zone->container->manager->root == e->event_win)))
5940                return ECORE_CALLBACK_PASS_ON;
5941           }
5942      }
5943    if (!bd) bd = e_border_find_by_client_window(e->win);
5944 //   printf("  bd = %p\n", bd);
5945    if (!bd)
5946      {
5947         if (ecore_x_window_visible_get(e->win))
5948           {
5949              ELB(ELBT_BD, "FORCE UNMAP client window", e->win);
5950              ecore_x_window_hide(e->win);
5951           }
5952         return ECORE_CALLBACK_PASS_ON;
5953      }
5954
5955 //   printf("  bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap);
5956    if (bd->ignore_first_unmap > 0)
5957      {
5958         bd->ignore_first_unmap--;
5959         return ECORE_CALLBACK_PASS_ON;
5960      }
5961    /* Don't delete hidden or iconified windows */
5962 #ifdef _F_USE_EXTENDED_ICONIFY_
5963    if (bd->await_hide_event > 0)
5964 #else
5965    if ((bd->iconic) || (bd->await_hide_event > 0))
5966 #endif
5967      {
5968 //        printf("  Don't delete hidden or iconified windows\n");
5969 //        printf("  bd->iconic = %i, bd->visible = %i, bd->new_client = %i, bd->await_hide_event = %i\n",
5970 //               bd->iconic, bd->visible, bd->new_client, bd->await_hide_event);
5971         if (bd->await_hide_event > 0)
5972           {
5973              bd->await_hide_event--;
5974           }
5975         else
5976           {
5977 //             printf("  hide really\n");
5978              /* Only hide the border if it is visible */
5979              if (bd->visible) e_border_hide(bd, 1);
5980           }
5981      }
5982    else
5983      {
5984 //             printf("  hide2\n");
5985 #ifdef _F_USE_EXTENDED_ICONIFY_
5986         if (bd->iconic)
5987           {
5988              bd->iconic = 0;
5989              bd->visible = 1;
5990           }
5991 #endif
5992
5993 #ifdef _F_ZONE_WINDOW_ROTATION_
5994         if (e_config->wm_win_rotation)
5995           {
5996              if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
5997                {
5998                   ELB(ELBT_BD, "X_UNMAP_NOTIFY", bd->client.win);
5999                   if (!rot.vkbd_hide_prepare_timer)
6000                     {
6001                        ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
6002                        e_border_hide(bd, 0);
6003                        if (!rot.vkbd_hide_prepare_timer)
6004                          {
6005                             ELB(ELBT_BD, "DEL VKBD", bd->client.win);
6006                             e_object_del(E_OBJECT(bd));
6007                          }
6008                     }
6009                   return ECORE_CALLBACK_PASS_ON;
6010                }
6011           }
6012 #endif
6013         e_border_hide(bd, 0);
6014         e_object_del(E_OBJECT(bd));
6015      }
6016    return ECORE_CALLBACK_PASS_ON;
6017 }
6018
6019 static Eina_Bool
6020 _e_border_cb_window_reparent(void *data  __UNUSED__,
6021                              int ev_type __UNUSED__,
6022                              void *ev    __UNUSED__)
6023 {
6024 #if 0
6025    E_Border *bd;
6026    Ecore_X_Event_Window_Reparent *e;
6027
6028    e = ev;
6029    bd = e_border_find_by_client_window(e->win);
6030    if (!bd) return 1;
6031    if (e->parent == bd->client.shell_win) return 1;
6032    if (ecore_x_window_parent_get(e->win) == bd->client.shell_win)
6033      {
6034         return 1;
6035      }
6036    e_border_hide(bd, 0);
6037    e_object_del(E_OBJECT(bd));
6038 #endif
6039    return ECORE_CALLBACK_PASS_ON;
6040 }
6041
6042 static Eina_Bool
6043 _e_border_cb_window_configure_request(void *data  __UNUSED__,
6044                                       int ev_type __UNUSED__,
6045                                       void       *ev)
6046 {
6047    E_Border *bd;
6048    Ecore_X_Event_Window_Configure_Request *e;
6049
6050    e = ev;
6051    bd = e_border_find_by_client_window(e->win);
6052    if (!bd)
6053      {
6054         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6055         if (!e_util_container_window_find(e->win))
6056           ecore_x_window_configure(e->win, e->value_mask,
6057                                    e->x, e->y, e->w, e->h, e->border,
6058                                    e->abovewin, e->detail);
6059         return ECORE_CALLBACK_PASS_ON;
6060      }
6061
6062    if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
6063        (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
6064      {
6065         int x, y;
6066
6067         x = bd->x;
6068         y = bd->y;
6069         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
6070           x = e->x;
6071         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
6072           y = e->y;
6073         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6074             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6075           {
6076              int w, h;
6077
6078              h = bd->h;
6079              w = bd->w;
6080              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6081                w = e->w + bd->client_inset.l + bd->client_inset.r;
6082              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6083                h = e->h + bd->client_inset.t + bd->client_inset.b;
6084              if ((!bd->lock_client_location) && (!bd->lock_client_size))
6085                {
6086                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6087                     {
6088                        bd->saved.x = x - bd->zone->x;
6089                        bd->saved.y = y - bd->zone->y;
6090                        bd->saved.w = w;
6091                        bd->saved.h = h;
6092                     }
6093                   else
6094                     e_border_move_resize(bd, x, y, w, h);
6095                }
6096              else if (!bd->lock_client_location)
6097                {
6098                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6099                     {
6100                        bd->saved.x = x - bd->zone->x;
6101                        bd->saved.y = y - bd->zone->y;
6102                     }
6103                   else
6104                     e_border_move(bd, x, y);
6105                }
6106              else if (!bd->lock_client_size)
6107                {
6108                   if ((bd->shaded) || (bd->shading))
6109                     {
6110                        int pw, ph;
6111
6112                        pw = bd->client.w;
6113                        ph = bd->client.h;
6114                        if ((bd->shade.dir == E_DIRECTION_UP) ||
6115                            (bd->shade.dir == E_DIRECTION_DOWN))
6116                          {
6117                             e_border_resize(bd, w, bd->h);
6118                             bd->client.h = ph;
6119                          }
6120                        else
6121                          {
6122                             e_border_resize(bd, bd->w, h);
6123                             bd->client.w = pw;
6124                          }
6125                     }
6126                   else
6127                     {
6128                        if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6129                          {
6130                             bd->saved.w = w;
6131                             bd->saved.h = h;
6132                          }
6133                        else
6134                          e_border_resize(bd, w, h);
6135                     }
6136                }
6137           }
6138         else
6139           {
6140              if (!bd->lock_client_location)
6141                {
6142                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6143                     {
6144                        bd->saved.x = x - bd->zone->x;
6145                        bd->saved.y = y - bd->zone->y;
6146                     }
6147                   else
6148                     e_border_move(bd, x, y);
6149                }
6150           }
6151      }
6152    else if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6153             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6154      {
6155         int w, h;
6156
6157         h = bd->h;
6158         w = bd->w;
6159         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6160           w = e->w + bd->client_inset.l + bd->client_inset.r;
6161         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6162           h = e->h + bd->client_inset.t + bd->client_inset.b;
6163 #ifdef _F_ZONE_WINDOW_ROTATION_
6164         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
6165 #endif
6166         if (!bd->lock_client_size)
6167           {
6168              if ((bd->shaded) || (bd->shading))
6169                {
6170                   int pw, ph;
6171
6172                   pw = bd->client.w;
6173                   ph = bd->client.h;
6174                   if ((bd->shade.dir == E_DIRECTION_UP) ||
6175                       (bd->shade.dir == E_DIRECTION_DOWN))
6176                     {
6177                        e_border_resize(bd, w, bd->h);
6178                        bd->client.h = ph;
6179                     }
6180                   else
6181                     {
6182                        e_border_resize(bd, bd->w, h);
6183                        bd->client.w = pw;
6184                     }
6185                }
6186              else
6187                {
6188                   if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE)
6189                     {
6190                        int zx, zy, zw, zh;
6191                        int rx = bd->x;
6192                        int ry = bd->y;
6193                        zx = zy = zw = zh = 0;
6194
6195      /*
6196       * This code does resize and move a window on a
6197       * X configure request into an useful geometry.
6198       * This is really useful for size jumping file dialogs.
6199       */
6200
6201                        if (bd->zone)
6202                          {
6203                             e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
6204
6205                             if (e_config->geometry_auto_resize_limit == 1)
6206                               {
6207                                  if (w > zw)
6208                                    w = zw;
6209
6210                                  if (h > zh)
6211                                    h = zh;
6212                               }
6213                          }
6214                        e_border_resize(bd, w, h);
6215
6216                        if (e_config->geometry_auto_move == 1)
6217                          {
6218                              /* z{x,y,w,h} are only set here; FIXME! */
6219                              if (bd->zone)
6220                                {
6221                                   // move window horizontal if resize to not useful geometry
6222                                   if (bd->x + bd->w > zx + zw)
6223                                     rx = zx + zw - bd->w;
6224                                   else if (bd->x < zx)
6225                                     rx = zx;
6226
6227                                   // move window vertical if resize to not useful geometry
6228                                   if (bd->y + bd->h > zy + zh)
6229                                     ry = zy + zh - bd->h;
6230                                   else if (bd->y < zy)
6231                                     ry = zy;
6232                                }
6233                              e_border_move(bd, rx, ry);
6234                          }
6235                     }
6236                }
6237           }
6238      }
6239    if (!bd->lock_client_stacking)
6240      {
6241         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
6242             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
6243           {
6244              E_Border *obd;
6245
6246              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6247                {
6248                   obd = e_border_find_by_client_window(e->abovewin);
6249                   if (obd)
6250                     {
6251                        e_border_stack_above(bd, obd);
6252                     }
6253                   else
6254                     {
6255                        ecore_x_window_configure(bd->win,
6256                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6257                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6258                                                 0, 0, 0, 0, 0,
6259                                                 e->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
6260                        /* FIXME: need to rebuiuld border list from current stacking */
6261                     }
6262                }
6263              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6264                {
6265                   obd = e_border_find_by_client_window(e->abovewin);
6266                   if (obd)
6267                     {
6268                        e_border_stack_below(bd, obd);
6269                     }
6270                   else
6271                     {
6272                        ecore_x_window_configure(bd->win,
6273                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6274                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6275                                                 0, 0, 0, 0, 0,
6276                                                 e->abovewin, ECORE_X_WINDOW_STACK_BELOW);
6277                        /* FIXME: need to rebuiuld border list from current stacking */
6278                     }
6279                }
6280              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6281                {
6282      /* FIXME: do */
6283                }
6284              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6285                {
6286      /* FIXME: do */
6287                }
6288              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6289                {
6290      /* FIXME: do */
6291                }
6292           }
6293         else if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
6294           {
6295              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6296                {
6297                   e_border_raise(bd);
6298                }
6299              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6300                {
6301                   e_border_lower(bd);
6302                }
6303              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6304                {
6305      /* FIXME: do */
6306                }
6307              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6308                {
6309      /* FIXME: do */
6310                }
6311              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6312                {
6313      /* FIXME: do */
6314                }
6315           }
6316      }
6317
6318    /* FIXME: need to send synthetic stacking event too as well as move/resize */
6319    _e_border_client_move_resize_send(bd);
6320    return ECORE_CALLBACK_PASS_ON;
6321 }
6322
6323 static Eina_Bool
6324 _e_border_cb_window_resize_request(void *data  __UNUSED__,
6325                                    int ev_type __UNUSED__,
6326                                    void       *ev)
6327 {
6328    E_Border *bd;
6329    Ecore_X_Event_Window_Resize_Request *e;
6330
6331    e = ev;
6332    bd = e_border_find_by_client_window(e->win);
6333    if (!bd)
6334      {
6335         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6336         ecore_x_window_resize(e->win, e->w, e->h);
6337         return ECORE_CALLBACK_PASS_ON;
6338      }
6339    {
6340       int w, h;
6341
6342       w = e->w + bd->client_inset.l + bd->client_inset.r;
6343       h = e->h + bd->client_inset.t + bd->client_inset.b;
6344       if ((bd->shaded) || (bd->shading))
6345         {
6346            int pw, ph;
6347
6348            pw = bd->client.w;
6349            ph = bd->client.h;
6350            if ((bd->shade.dir == E_DIRECTION_UP) ||
6351                (bd->shade.dir == E_DIRECTION_DOWN))
6352              {
6353                 e_border_resize(bd, w, bd->h);
6354                 bd->client.h = ph;
6355              }
6356            else
6357              {
6358                 e_border_resize(bd, bd->w, h);
6359                 bd->client.w = pw;
6360              }
6361         }
6362       else
6363         e_border_resize(bd, w, h);
6364    }
6365
6366    _e_border_client_move_resize_send(bd);
6367    return ECORE_CALLBACK_PASS_ON;
6368 }
6369
6370 static Eina_Bool
6371 _e_border_cb_window_gravity(void *data  __UNUSED__,
6372                             int ev_type __UNUSED__,
6373                             void *ev    __UNUSED__)
6374 {
6375 //   E_Border *bd;
6376 //   Ecore_X_Event_Window_Gravity *e;
6377
6378 //   e = ev;
6379 //   bd = e_border_find_by_client_window(e->win);
6380 //   if (!bd) return 1;
6381              return 1;
6382 }
6383
6384 static Eina_Bool
6385 _e_border_cb_window_stack_request(void *data  __UNUSED__,
6386                                   int ev_type __UNUSED__,
6387                                   void       *ev)
6388 {
6389    E_Border *bd;
6390    Ecore_X_Event_Window_Stack_Request *e;
6391
6392    e = ev;
6393    bd = e_border_find_by_client_window(e->win);
6394    if (!bd)
6395      {
6396         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6397         if (!e_util_container_window_find(e->win))
6398           {
6399              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6400                ecore_x_window_raise(e->win);
6401              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6402                ecore_x_window_lower(e->win);
6403           }
6404         return ECORE_CALLBACK_PASS_ON;
6405      }
6406    if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6407      e_border_raise(bd);
6408    else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6409      e_border_lower(bd);
6410    return ECORE_CALLBACK_PASS_ON;
6411 }
6412
6413 static Eina_Bool
6414 _e_border_cb_window_property(void *data  __UNUSED__,
6415                              int ev_type __UNUSED__,
6416                              void       *ev)
6417 {
6418    E_Border *bd;
6419    Ecore_X_Event_Window_Property *e;
6420
6421    e = ev;
6422    bd = e_border_find_by_client_window(e->win);
6423    if (!bd) return ECORE_CALLBACK_PASS_ON;
6424    if (e->atom == ECORE_X_ATOM_WM_NAME)
6425      {
6426         if ((!bd->client.netwm.name) &&
6427             (!bd->client.netwm.fetch.name))
6428           {
6429              bd->client.icccm.fetch.title = 1;
6430              bd->changed = 1;
6431           }
6432      }
6433    else if (e->atom == ECORE_X_ATOM_NET_WM_NAME)
6434      {
6435         bd->client.netwm.fetch.name = 1;
6436         bd->changed = 1;
6437      }
6438    else if (e->atom == ECORE_X_ATOM_WM_CLASS)
6439      {
6440         bd->client.icccm.fetch.name_class = 1;
6441         bd->changed = 1;
6442      }
6443    else if (e->atom == ECORE_X_ATOM_WM_ICON_NAME)
6444      {
6445         if ((!bd->client.netwm.icon_name) &&
6446             (!bd->client.netwm.fetch.icon_name))
6447           {
6448              bd->client.icccm.fetch.icon_name = 1;
6449              bd->changed = 1;
6450           }
6451      }
6452    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
6453      {
6454         bd->client.netwm.fetch.icon_name = 1;
6455         bd->changed = 1;
6456      }
6457    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
6458      {
6459         bd->client.icccm.fetch.machine = 1;
6460         bd->changed = 1;
6461      }
6462    else if (e->atom == ECORE_X_ATOM_WM_PROTOCOLS)
6463      {
6464         bd->client.icccm.fetch.protocol = 1;
6465         bd->changed = 1;
6466      }
6467    else if (e->atom == ECORE_X_ATOM_WM_HINTS)
6468      {
6469         bd->client.icccm.fetch.hints = 1;
6470         bd->changed = 1;
6471      }
6472    else if (e->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
6473      {
6474         bd->client.icccm.fetch.size_pos_hints = 1;
6475         bd->changed = 1;
6476      }
6477    else if (e->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
6478      {
6479         /*
6480            if ((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN) &&
6481             (!bd->client.netwm.fetch.type))
6482            {
6483          */
6484           bd->client.mwm.fetch.hints = 1;
6485           bd->changed = 1;
6486           /*
6487              }
6488            */
6489      }
6490    else if (e->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
6491      {
6492         bd->client.icccm.fetch.transient_for = 1;
6493         bd->changed = 1;
6494      }
6495    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
6496      {
6497         bd->client.icccm.fetch.client_leader = 1;
6498         bd->changed = 1;
6499      }
6500    else if (e->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
6501      {
6502         bd->client.icccm.fetch.window_role = 1;
6503         bd->changed = 1;
6504      }
6505    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON)
6506      {
6507         bd->client.netwm.fetch.icon = 1;
6508         bd->changed = 1;
6509      }
6510    else if (e->atom == ATM__QTOPIA_SOFT_MENU)
6511      {
6512         bd->client.qtopia.fetch.soft_menu = 1;
6513         bd->changed = 1;
6514      }
6515    else if (e->atom == ATM__QTOPIA_SOFT_MENUS)
6516      {
6517         bd->client.qtopia.fetch.soft_menus = 1;
6518         bd->changed = 1;
6519      }
6520    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
6521      {
6522         bd->client.vkbd.fetch.state = 1;
6523         bd->changed = 1;
6524      }
6525    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
6526      {
6527         bd->client.vkbd.fetch.vkbd = 1;
6528         bd->changed = 1;
6529      }
6530    else if (e->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
6531      {
6532         bd->client.illume.conformant.fetch.conformant = 1;
6533         bd->changed = 1;
6534      }
6535    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
6536      {
6537         bd->client.illume.quickpanel.fetch.state = 1;
6538         bd->changed = 1;
6539      }
6540    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
6541      {
6542         bd->client.illume.quickpanel.fetch.quickpanel = 1;
6543         bd->changed = 1;
6544      }
6545    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
6546      {
6547         bd->client.illume.quickpanel.fetch.priority.major = 1;
6548         bd->changed = 1;
6549      }
6550    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
6551      {
6552         bd->client.illume.quickpanel.fetch.priority.minor = 1;
6553         bd->changed = 1;
6554      }
6555    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
6556      {
6557         bd->client.illume.quickpanel.fetch.zone = 1;
6558         bd->changed = 1;
6559      }
6560    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
6561      {
6562         bd->client.illume.drag.fetch.locked = 1;
6563         bd->changed = 1;
6564      }
6565    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
6566      {
6567         bd->client.illume.drag.fetch.drag = 1;
6568         bd->changed = 1;
6569      }
6570    else if (e->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
6571      {
6572         bd->client.illume.win_state.fetch.state = 1;
6573         bd->changed = 1;
6574      }
6575    /*
6576       else if (e->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
6577       {
6578         bd->client.netwm.fetch.user_time = 1;
6579         bd->changed = 1;
6580       }
6581       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT)
6582       {
6583         bd->client.netwm.fetch.strut = 1;
6584         bd->changed = 1;
6585       }
6586       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
6587       {
6588         bd->client.netwm.fetch.strut = 1;
6589         bd->changed = 1;
6590       }
6591     */
6592    else if (e->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
6593      {
6594         //printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
6595      }
6596    else if (e->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
6597      {
6598         bd->client.e.fetch.video_position = 1;
6599         bd->changed = 1;
6600      }
6601    else if (e->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
6602      {
6603         bd->client.e.fetch.video_parent = 1;
6604         bd->changed = 1;
6605      }
6606    else if (e->atom == ECORE_X_ATOM_NET_WM_STATE)
6607      {
6608         bd->client.netwm.fetch.state = 1;
6609         bd->changed = 1;
6610      }
6611 #ifdef _F_USE_DESK_WINDOW_PROFILE_
6612    else if (e->atom == ECORE_X_ATOM_E_PROFILE_LIST)
6613      {
6614         bd->client.e.fetch.profile_list = 1;
6615         bd->changed = 1;
6616      }
6617 #endif
6618 #ifdef _F_ZONE_WINDOW_ROTATION_
6619    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED)
6620      {
6621         if (e_config->wm_win_rotation)
6622           {
6623              bd->client.e.fetch.rot.support = 1;
6624              bd->changed = 1;
6625           }
6626      }
6627    else if ((e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) ||
6628             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) ||
6629             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) ||
6630             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY))
6631      {
6632         if (e_config->wm_win_rotation)
6633           {
6634              bd->client.e.fetch.rot.geom_hint = 1;
6635              bd->changed = 1;
6636           }
6637      }
6638    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED)
6639      {
6640         if (e_config->wm_win_rotation)
6641           {
6642              bd->client.e.fetch.rot.app_set = 1;
6643              bd->changed = 1;
6644           }
6645      }
6646    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION)
6647      {
6648         if (e_config->wm_win_rotation)
6649           {
6650              bd->client.e.fetch.rot.preferred_rot = 1;
6651              bd->changed = 1;
6652           }
6653      }
6654    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)
6655      {
6656         if (e_config->wm_win_rotation)
6657           {
6658              bd->client.e.fetch.rot.available_rots = 1;
6659              bd->changed = 1;
6660           }
6661      }
6662 #endif
6663
6664    return ECORE_CALLBACK_PASS_ON;
6665 }
6666
6667 static Eina_Bool
6668 _e_border_cb_window_colormap(void *data  __UNUSED__,
6669                              int ev_type __UNUSED__,
6670                              void       *ev)
6671 {
6672    E_Border *bd;
6673    Ecore_X_Event_Window_Colormap *e;
6674
6675    e = ev;
6676    bd = e_border_find_by_client_window(e->win);
6677    if (!bd) return ECORE_CALLBACK_PASS_ON;
6678    return ECORE_CALLBACK_PASS_ON;
6679 }
6680
6681 static Eina_Bool
6682 _e_border_cb_window_shape(void *data  __UNUSED__,
6683                           int ev_type __UNUSED__,
6684                           void       *ev)
6685 {
6686    E_Border *bd;
6687    Ecore_X_Event_Window_Shape *e;
6688
6689    e = ev;
6690    bd = e_border_find_by_client_window(e->win);
6691
6692    if (e->type == ECORE_X_SHAPE_INPUT)
6693      {
6694         if (bd)
6695           {
6696              bd->need_shape_merge = 1;
6697 // YYY             bd->shaped_input = 1;
6698              bd->changes.shape_input = 1;
6699              bd->changed = 1;
6700           }
6701
6702         return ECORE_CALLBACK_PASS_ON;
6703      }
6704
6705    if (bd)
6706      {
6707         bd->changes.shape = 1;
6708         bd->changed = 1;
6709         return ECORE_CALLBACK_PASS_ON;
6710      }
6711    bd = e_border_find_by_window(e->win);
6712    if (bd)
6713      {
6714         bd->need_shape_export = 1;
6715         bd->changed = 1;
6716         return ECORE_CALLBACK_PASS_ON;
6717      }
6718    bd = e_border_find_by_frame_window(e->win);
6719    if (bd)
6720      {
6721         bd->need_shape_merge = 1;
6722         bd->changed = 1;
6723         return ECORE_CALLBACK_PASS_ON;
6724      }
6725    return ECORE_CALLBACK_PASS_ON;
6726 }
6727
6728 static Eina_Bool
6729 _e_border_cb_window_focus_in(void *data  __UNUSED__,
6730                              int ev_type __UNUSED__,
6731                              void       *ev)
6732 {
6733    E_Border *bd;
6734    Ecore_X_Event_Window_Focus_In *e;
6735
6736    e = ev;
6737    bd = e_border_find_by_client_window(e->win);
6738    if (!bd) return ECORE_CALLBACK_PASS_ON;
6739 #ifdef INOUTDEBUG_FOCUS
6740    {
6741       time_t t;
6742       char *ct;
6743
6744       const char *modes[] = {
6745         "MODE_NORMAL",
6746         "MODE_WHILE_GRABBED",
6747         "MODE_GRAB",
6748         "MODE_UNGRAB"
6749       };
6750       const char *details[] = {
6751         "DETAIL_ANCESTOR",
6752         "DETAIL_VIRTUAL",
6753         "DETAIL_INFERIOR",
6754         "DETAIL_NON_LINEAR",
6755         "DETAIL_NON_LINEAR_VIRTUAL",
6756         "DETAIL_POINTER",
6757         "DETAIL_POINTER_ROOT",
6758         "DETAIL_DETAIL_NONE"
6759       };
6760       t = time(NULL);
6761       ct = ctime(&t);
6762       ct[strlen(ct) - 1] = 0;
6763       DBG("FF ->IN %i 0x%x %s md=%s dt=%s\n",
6764              e->time,
6765              e->win,
6766              ct,
6767              modes[e->mode],
6768              details[e->detail]);
6769
6770       DBG("%s cb focus in %d %d\n",
6771              e_border_name_get(bd),
6772              bd->client.icccm.accepts_focus,
6773              bd->client.icccm.take_focus);
6774    }
6775 #endif
6776    _e_border_pri_raise(bd);
6777    if (e->mode == ECORE_X_EVENT_MODE_GRAB)
6778      {
6779         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
6780      }
6781    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
6782      {
6783         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
6784      }
6785
6786    /* ignore focus in from !take_focus windows, we just gave it em */
6787    /* if (!bd->client.icccm.take_focus)
6788     *   return ECORE_CALLBACK_PASS_ON; */
6789
6790    /* should be equal, maybe some clients dont reply with the proper timestamp ? */
6791    if (e->time >= focus_time)
6792      e_border_focus_set(bd, 1, 0);
6793    return ECORE_CALLBACK_PASS_ON;
6794 }
6795
6796 static Eina_Bool
6797 _e_border_cb_window_focus_out(void *data  __UNUSED__,
6798                               int ev_type __UNUSED__,
6799                               void       *ev)
6800 {
6801    E_Border *bd;
6802    Ecore_X_Event_Window_Focus_Out *e;
6803
6804    e = ev;
6805    bd = e_border_find_by_client_window(e->win);
6806    if (!bd) return ECORE_CALLBACK_PASS_ON;
6807 #ifdef INOUTDEBUG_FOCUS
6808    {
6809       time_t t;
6810       char *ct;
6811
6812       const char *modes[] = {
6813         "MODE_NORMAL",
6814         "MODE_WHILE_GRABBED",
6815         "MODE_GRAB",
6816         "MODE_UNGRAB"
6817       };
6818       const char *details[] = {
6819         "DETAIL_ANCESTOR",
6820         "DETAIL_VIRTUAL",
6821         "DETAIL_INFERIOR",
6822         "DETAIL_NON_LINEAR",
6823         "DETAIL_NON_LINEAR_VIRTUAL",
6824         "DETAIL_POINTER",
6825         "DETAIL_POINTER_ROOT",
6826         "DETAIL_DETAIL_NONE"
6827       };
6828       t = time(NULL);
6829       ct = ctime(&t);
6830       ct[strlen(ct) - 1] = 0;
6831       DBG("FF <-OUT %i 0x%x %s md=%s dt=%s",
6832              e->time,
6833              e->win,
6834              ct,
6835              modes[e->mode],
6836              details[e->detail]);
6837
6838       DBG("%s cb focus out %d %d",
6839              e_border_name_get(bd),
6840              bd->client.icccm.accepts_focus,
6841              bd->client.icccm.take_focus);
6842    }
6843 #endif
6844    _e_border_pri_norm(bd);
6845    if (e->mode == ECORE_X_EVENT_MODE_NORMAL)
6846      {
6847         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
6848         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
6849           return ECORE_CALLBACK_PASS_ON;
6850         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
6851           return ECORE_CALLBACK_PASS_ON;
6852      }
6853    else if (e->mode == ECORE_X_EVENT_MODE_GRAB)
6854      {
6855         if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR) return ECORE_CALLBACK_PASS_ON;
6856         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
6857           return ECORE_CALLBACK_PASS_ON;
6858         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
6859           return ECORE_CALLBACK_PASS_ON;
6860         else if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
6861           return ECORE_CALLBACK_PASS_ON;
6862         else if (e->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
6863           return ECORE_CALLBACK_PASS_ON;
6864      }
6865    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
6866      {
6867         /* for firefox/thunderbird (xul) menu walking */
6868         /* NB: why did i disable this before? */
6869         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
6870         else if (e->detail == ECORE_X_EVENT_DETAIL_POINTER)
6871           return ECORE_CALLBACK_PASS_ON;
6872      }
6873    else if (e->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
6874      {
6875         if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR) return ECORE_CALLBACK_PASS_ON;
6876         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
6877           return ECORE_CALLBACK_PASS_ON;
6878      }
6879    e_border_focus_set(bd, 0, 0);
6880    return ECORE_CALLBACK_PASS_ON;
6881 }
6882
6883 #if _F_BORDER_CLIP_TO_ZONE_
6884 static void
6885 _e_border_shape_input_clip_to_zone(E_Border *bd)
6886 {
6887    /* if (!(e_config->window_out_of_vscreen_limits_partly)) return; */
6888    if (!(bd->visible))
6889      return;
6890
6891    if (!(E_CONTAINS(bd->zone->x, bd->zone->y,
6892                     bd->zone->w, bd->zone->h,
6893                     bd->x, bd->y, bd->w, bd->h)))
6894      {
6895         int x, y, w, h;
6896         x = bd->x; y = bd->y; w = bd->w; h = bd->h;
6897         E_RECTS_CLIP_TO_RECT(x, y, w, h,
6898                              bd->zone->x, bd->zone->y,
6899                              bd->zone->w, bd->zone->h);
6900         x -= bd->x;
6901         y -= bd->y;
6902         ecore_x_window_shape_input_rectangle_set(bd->bg_win, x, y, w, h);
6903         ecore_x_window_shape_input_rectangle_set(bd->win, x, y, w, h);
6904      }
6905    else
6906      {
6907         ecore_x_window_shape_input_rectangle_set(bd->bg_win, 0, 0, bd->w, bd->h);
6908         ecore_x_window_shape_input_rectangle_set(bd->win, 0, 0, bd->w, bd->h);
6909      }
6910 }
6911 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
6912
6913 static Eina_Bool
6914 _e_border_cb_client_message(void *data  __UNUSED__,
6915                             int ev_type __UNUSED__,
6916                             void       *ev)
6917 {
6918    Ecore_X_Event_Client_Message *e;
6919    E_Border *bd;
6920
6921    e = ev;
6922 #ifdef _F_DEICONIFY_APPROVE_
6923    if (e->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
6924      {
6925         if (!e_config->deiconify_approve) return ECORE_CALLBACK_PASS_ON;
6926
6927         bd = e_border_find_by_client_window(e->win);
6928         if (bd)
6929           {
6930              if (bd->client.e.state.deiconify_approve.support)
6931                {
6932                   if (e->data.l[1] != 1) return ECORE_CALLBACK_PASS_ON;
6933                   bd->client.e.state.deiconify_approve.render_done = 1;
6934
6935                   E_Border *ancestor_bd;
6936                   ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
6937                   if (ancestor_bd)
6938                     {
6939                        ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
6940                        bd->client.e.state.deiconify_approve.ancestor = NULL;
6941                     }
6942                   else
6943                     {
6944                        ancestor_bd = bd;
6945                     }
6946
6947                   ELBF(ELBT_BD, 0, bd->client.win,
6948                        "RECEIVE DEICONIFY_APPROVE.. ancestor:%x", ancestor_bd->client.win);
6949
6950                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
6951                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
6952                     {
6953                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
6954                          {
6955                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
6956                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
6957                             e_border_uniconify(ancestor_bd);
6958                          }
6959                        else
6960                          {
6961                             ELB(ELBT_BD, "Unset DEICONIFY_APPROVE render_done", ancestor_bd->client.win);
6962                             ancestor_bd->client.e.state.deiconify_approve.render_done = 0;
6963                          }
6964                     }
6965                }
6966           }
6967         return ECORE_CALLBACK_PASS_ON;
6968      }
6969 #endif
6970
6971 #ifdef _F_ZONE_WINDOW_ROTATION_
6972    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
6973
6974    bd = e_border_find_by_client_window(e->win);
6975    if (!bd)
6976      {
6977         if (e_config->wm_win_rotation)
6978           {
6979              Ecore_X_Event_Client_Message *msg = NULL;
6980              Ecore_X_Atom t = e->message_type;
6981              if ((t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)  ||
6982                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE) ||
6983                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)   ||
6984                  (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE))
6985                {
6986                   msg = E_NEW(Ecore_X_Event_Client_Message, 1);
6987                   if (!msg) return ECORE_CALLBACK_PASS_ON;
6988
6989                   msg->win = e->win;
6990                   msg->message_type = e->message_type;
6991                   msg->data.l[0] = e->data.l[0];
6992                   msg->data.l[1] = e->data.l[1];
6993                   msg->data.l[2] = e->data.l[2];
6994                   msg->data.l[3] = e->data.l[3];
6995                   msg->data.l[4] = e->data.l[4];
6996                   rot.msgs = eina_list_append(rot.msgs, msg);
6997
6998                   rot.fetch = EINA_TRUE;
6999                }
7000           }
7001         return ECORE_CALLBACK_PASS_ON;
7002      }
7003
7004    if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE)
7005      {
7006         ELBF(ELBT_ROT, 0, e->data.l[0], "GET ROT_DONE a%d %dx%d zone_a:%d",
7007              e->data.l[1], e->data.l[2], e->data.l[3], bd->zone->rot.curr);
7008
7009         if (e_config->wm_win_rotation)
7010           {
7011              if ((int)e->data.l[1] == bd->client.e.state.rot.curr)
7012                _e_border_rotation_list_remove(bd);
7013           }
7014      }
7015 #endif
7016    return ECORE_CALLBACK_PASS_ON;
7017 }
7018
7019 static Eina_Bool
7020 _e_border_cb_window_state_request(void *data  __UNUSED__,
7021                                   int ev_type __UNUSED__,
7022                                   void       *ev)
7023 {
7024    E_Border *bd;
7025    Ecore_X_Event_Window_State_Request *e;
7026    int i;
7027
7028    e = ev;
7029    bd = e_border_find_by_client_window(e->win);
7030    if (!bd) return ECORE_CALLBACK_PASS_ON;
7031
7032    for (i = 0; i < 2; i++)
7033      e_hints_window_state_update(bd, e->state[i], e->action);
7034
7035    return ECORE_CALLBACK_PASS_ON;
7036 }
7037
7038 static Eina_Bool
7039 _e_border_cb_window_move_resize_request(void *data  __UNUSED__,
7040                                         int ev_type __UNUSED__,
7041                                         void       *ev)
7042 {
7043    E_Border *bd;
7044    Ecore_X_Event_Window_Move_Resize_Request *e;
7045
7046    e = ev;
7047    bd = e_border_find_by_client_window(e->win);
7048    if (!bd) return ECORE_CALLBACK_PASS_ON;
7049
7050    if ((bd->shaded) || (bd->shading) ||
7051        (bd->fullscreen) || (bd->moving) ||
7052        (bd->resize_mode != RESIZE_NONE))
7053      return ECORE_CALLBACK_PASS_ON;
7054
7055    if ((e->button >= 1) && (e->button <= 3))
7056      {
7057         bd->mouse.last_down[e->button - 1].mx = e->x;
7058         bd->mouse.last_down[e->button - 1].my = e->y;
7059         bd->mouse.last_down[e->button - 1].x = bd->x;
7060         bd->mouse.last_down[e->button - 1].y = bd->y;
7061         bd->mouse.last_down[e->button - 1].w = bd->w;
7062         bd->mouse.last_down[e->button - 1].h = bd->h;
7063      }
7064    else
7065      {
7066         bd->moveinfo.down.x = bd->x;
7067         bd->moveinfo.down.y = bd->y;
7068         bd->moveinfo.down.w = bd->w;
7069         bd->moveinfo.down.h = bd->h;
7070      }
7071    bd->mouse.current.mx = e->x;
7072    bd->mouse.current.my = e->y;
7073    bd->moveinfo.down.button = e->button;
7074    bd->moveinfo.down.mx = e->x;
7075    bd->moveinfo.down.my = e->y;
7076    grabbed = 1;
7077
7078    if (!bd->lock_user_stacking)
7079      e_border_raise(bd);
7080
7081    if (e->direction == MOVE)
7082      {
7083         bd->cur_mouse_action = e_action_find("window_move");
7084         if (bd->cur_mouse_action)
7085           {
7086              if ((!bd->cur_mouse_action->func.end_mouse) &&
7087                  (!bd->cur_mouse_action->func.end))
7088                bd->cur_mouse_action = NULL;
7089              if (bd->cur_mouse_action)
7090                {
7091                   e_object_ref(E_OBJECT(bd->cur_mouse_action));
7092                   bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
7093                }
7094           }
7095         return ECORE_CALLBACK_PASS_ON;
7096      }
7097
7098    if (!_e_border_resize_begin(bd))
7099      return ECORE_CALLBACK_PASS_ON;
7100
7101    switch (e->direction)
7102      {
7103       case RESIZE_TL:
7104         bd->resize_mode = RESIZE_TL;
7105         GRAV_SET(bd, ECORE_X_GRAVITY_SE);
7106         break;
7107
7108       case RESIZE_T:
7109         bd->resize_mode = RESIZE_T;
7110         GRAV_SET(bd, ECORE_X_GRAVITY_S);
7111         break;
7112
7113       case RESIZE_TR:
7114         bd->resize_mode = RESIZE_TR;
7115         GRAV_SET(bd, ECORE_X_GRAVITY_SW);
7116         break;
7117
7118       case RESIZE_R:
7119         bd->resize_mode = RESIZE_R;
7120         GRAV_SET(bd, ECORE_X_GRAVITY_W);
7121         break;
7122
7123       case RESIZE_BR:
7124         bd->resize_mode = RESIZE_BR;
7125         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
7126         break;
7127
7128       case RESIZE_B:
7129         bd->resize_mode = RESIZE_B;
7130         GRAV_SET(bd, ECORE_X_GRAVITY_N);
7131         break;
7132
7133       case RESIZE_BL:
7134         bd->resize_mode = RESIZE_BL;
7135         GRAV_SET(bd, ECORE_X_GRAVITY_NE);
7136         break;
7137
7138       case RESIZE_L:
7139         bd->resize_mode = RESIZE_L;
7140         GRAV_SET(bd, ECORE_X_GRAVITY_E);
7141         break;
7142
7143       default:
7144         return ECORE_CALLBACK_PASS_ON;
7145      }
7146
7147    bd->cur_mouse_action = e_action_find("window_resize");
7148    if (bd->cur_mouse_action)
7149      {
7150         if ((!bd->cur_mouse_action->func.end_mouse) &&
7151             (!bd->cur_mouse_action->func.end))
7152           bd->cur_mouse_action = NULL;
7153      }
7154    if (bd->cur_mouse_action)
7155      e_object_ref(E_OBJECT(bd->cur_mouse_action));
7156
7157    return ECORE_CALLBACK_PASS_ON;
7158 }
7159
7160 static Eina_Bool
7161 _e_border_cb_desktop_change(void *data  __UNUSED__,
7162                             int ev_type __UNUSED__,
7163                             void       *ev)
7164 {
7165    E_Border *bd;
7166    Ecore_X_Event_Desktop_Change *e;
7167
7168    e = ev;
7169    bd = e_border_find_by_client_window(e->win);
7170    if (bd)
7171      {
7172         if (e->desk == 0xffffffff)
7173           e_border_stick(bd);
7174         else if ((int)e->desk < (bd->zone->desk_x_count * bd->zone->desk_y_count))
7175           {
7176              E_Desk *desk;
7177
7178              desk = e_desk_at_pos_get(bd->zone, e->desk);
7179              if (desk)
7180                e_border_desk_set(bd, desk);
7181           }
7182      }
7183    else
7184      {
7185         ecore_x_netwm_desktop_set(e->win, e->desk);
7186      }
7187    return ECORE_CALLBACK_PASS_ON;
7188 }
7189
7190 static Eina_Bool
7191 _e_border_cb_sync_alarm(void *data  __UNUSED__,
7192                         int ev_type __UNUSED__,
7193                         void       *ev)
7194 {
7195    E_Border *bd;
7196    Ecore_X_Event_Sync_Alarm *e;
7197    unsigned int serial;
7198
7199    e = ev;
7200    bd = e_border_find_by_alarm(e->alarm);
7201    if (!bd) return ECORE_CALLBACK_PASS_ON;
7202
7203    if (bd->client.netwm.sync.wait)
7204      bd->client.netwm.sync.wait--;
7205
7206    if (ecore_x_sync_counter_query(bd->client.netwm.sync.counter, &serial))
7207      {
7208         E_Border_Pending_Move_Resize *pnd = NULL;
7209
7210         /* skip pending for which we didn't get a reply */
7211         while (bd->pending_move_resize)
7212           {
7213              pnd = bd->pending_move_resize->data;
7214              bd->pending_move_resize = eina_list_remove(bd->pending_move_resize, pnd);
7215
7216              if (serial == pnd->serial)
7217                break;
7218
7219              E_FREE(pnd);
7220           }
7221
7222         if (pnd)
7223           {
7224              bd->x = pnd->x;
7225              bd->y = pnd->y;
7226              bd->w = pnd->w;
7227              bd->h = pnd->h;
7228              bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
7229              bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
7230              E_FREE(pnd);
7231           }
7232      }
7233
7234    bd->changes.size = 1;
7235    bd->changes.pos = 1;
7236
7237    _e_border_eval(bd);
7238    evas_render(bd->bg_evas);
7239
7240    ecore_x_pointer_xy_get(e_manager_current_get()->root,
7241                           &bd->mouse.current.mx,
7242                           &bd->mouse.current.my);
7243
7244    bd->client.netwm.sync.send_time = ecore_loop_time_get();
7245    _e_border_resize_handle(bd);
7246
7247    return ECORE_CALLBACK_PASS_ON;
7248 }
7249
7250 static Eina_Bool
7251 _e_border_cb_efreet_cache_update(void *data  __UNUSED__,
7252                                  int ev_type __UNUSED__,
7253                                  void *ev    __UNUSED__)
7254 {
7255    Eina_List *l;
7256    E_Border *bd;
7257
7258    /* mark all borders for desktop/icon updates */
7259    EINA_LIST_FOREACH(borders, l, bd)
7260      {
7261         if (bd->desktop)
7262           {
7263              efreet_desktop_free(bd->desktop);
7264              bd->desktop = NULL;
7265           }
7266         bd->changes.icon = 1;
7267         bd->changed = 1;
7268      }
7269    /*
7270       e_init_status_set(_("Desktop files scan done"));
7271       e_init_done();
7272     */
7273    return ECORE_CALLBACK_PASS_ON;
7274 }
7275
7276 static Eina_Bool
7277 _e_border_cb_config_icon_theme(void *data  __UNUSED__,
7278                                int ev_type __UNUSED__,
7279                                void *ev    __UNUSED__)
7280 {
7281    Eina_List *l;
7282    E_Border *bd;
7283
7284    /* mark all borders for desktop/icon updates */
7285    EINA_LIST_FOREACH(borders, l, bd)
7286      {
7287         bd->changes.icon = 1;
7288         bd->changed = 1;
7289      }
7290    return ECORE_CALLBACK_PASS_ON;
7291 }
7292
7293 static Eina_Bool
7294 _e_border_cb_pointer_warp(void *data  __UNUSED__,
7295                           int ev_type __UNUSED__,
7296                           void       *ev)
7297 {
7298    E_Event_Pointer_Warp *e;
7299
7300    e = ev;
7301    if (!bdmove) return ECORE_CALLBACK_PASS_ON;
7302    e_border_move(bdmove, bdmove->x + (e->curr.x - e->prev.x), bdmove->y + (e->curr.y - e->prev.y));
7303    return ECORE_CALLBACK_PASS_ON;
7304 }
7305
7306 static void
7307 _e_border_cb_signal_bind(void            *data,
7308                          Evas_Object *obj __UNUSED__,
7309                          const char      *emission,
7310                          const char      *source)
7311 {
7312    E_Border *bd;
7313
7314    bd = data;
7315    if (e_dnd_active()) return;
7316    e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd),
7317                             emission, source);
7318 }
7319
7320 static Eina_Bool
7321 _e_border_cb_mouse_in(void    *data,
7322                       int type __UNUSED__,
7323                       void    *event)
7324 {
7325    Ecore_X_Event_Mouse_In *ev;
7326    E_Border *bd;
7327
7328    ev = event;
7329    bd = data;
7330 #ifdef INOUTDEBUG_MOUSE
7331    {
7332       time_t t;
7333       char *ct;
7334
7335       const char *modes[] = {
7336          "MODE_NORMAL",
7337          "MODE_WHILE_GRABBED",
7338          "MODE_GRAB",
7339          "MODE_UNGRAB"
7340       };
7341       const char *details[] = {
7342          "DETAIL_ANCESTOR",
7343          "DETAIL_VIRTUAL",
7344          "DETAIL_INFERIOR",
7345          "DETAIL_NON_LINEAR",
7346          "DETAIL_NON_LINEAR_VIRTUAL",
7347          "DETAIL_POINTER",
7348          "DETAIL_POINTER_ROOT",
7349          "DETAIL_DETAIL_NONE"
7350       };
7351       t = time(NULL);
7352       ct = ctime(&t);
7353       ct[strlen(ct) - 1] = 0;
7354       DBG("@@ ->IN 0x%x 0x%x %s md=%s dt=%s",
7355              ev->win, ev->event_win,
7356              ct,
7357              modes[ev->mode],
7358              details[ev->detail]);
7359    }
7360 #endif
7361    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7362    if (ev->event_win == bd->win)
7363      {
7364         e_focus_event_mouse_in(bd);
7365      }
7366 #if 0
7367    if ((ev->win != bd->win) &&
7368        (ev->win != bd->event_win) &&
7369        (ev->event_win != bd->win) &&
7370        (ev->event_win != bd->event_win))
7371      return ECORE_CALLBACK_PASS_ON;
7372 #else
7373    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7374 #endif
7375    bd->mouse.current.mx = ev->root.x;
7376    bd->mouse.current.my = ev->root.y;
7377    if (!bd->bg_evas_in)
7378      {
7379         evas_event_feed_mouse_in(bd->bg_evas, ev->time, NULL);
7380         bd->bg_evas_in = EINA_TRUE;
7381      }
7382    return ECORE_CALLBACK_PASS_ON;
7383 }
7384
7385 static Eina_Bool
7386 _e_border_cb_mouse_out(void    *data,
7387                        int type __UNUSED__,
7388                        void    *event)
7389 {
7390    Ecore_X_Event_Mouse_Out *ev;
7391    E_Border *bd;
7392
7393    ev = event;
7394    bd = data;
7395 #ifdef INOUTDEBUG_MOUSE
7396    {
7397       time_t t;
7398       char *ct;
7399
7400       const char *modes[] = {
7401          "MODE_NORMAL",
7402          "MODE_WHILE_GRABBED",
7403          "MODE_GRAB",
7404          "MODE_UNGRAB"
7405       };
7406       const char *details[] = {
7407          "DETAIL_ANCESTOR",
7408          "DETAIL_VIRTUAL",
7409          "DETAIL_INFERIOR",
7410          "DETAIL_NON_LINEAR",
7411          "DETAIL_NON_LINEAR_VIRTUAL",
7412          "DETAIL_POINTER",
7413          "DETAIL_POINTER_ROOT",
7414          "DETAIL_DETAIL_NONE"
7415       };
7416       t = time(NULL);
7417       ct = ctime(&t);
7418       ct[strlen(ct) - 1] = 0;
7419       DBG("@@ <-OUT 0x%x 0x%x %s md=%s dt=%s",
7420              ev->win, ev->event_win,
7421              ct,
7422              modes[ev->mode],
7423              details[ev->detail]);
7424    }
7425 #endif
7426    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7427    if (ev->event_win == bd->win)
7428      {
7429         if (bd->fullscreen)
7430           return ECORE_CALLBACK_PASS_ON;
7431         if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
7432             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7433           return ECORE_CALLBACK_PASS_ON;
7434         if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7435           return ECORE_CALLBACK_PASS_ON;
7436         if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
7437             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7438           return ECORE_CALLBACK_PASS_ON;
7439         e_focus_event_mouse_out(bd);
7440      }
7441 #if 0
7442    if ((ev->win != bd->win) &&
7443        (ev->win != bd->event_win) &&
7444        (ev->event_win != bd->win) &&
7445        (ev->event_win != bd->event_win))
7446      return ECORE_CALLBACK_PASS_ON;
7447 #else
7448    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7449 #endif
7450    bd->mouse.current.mx = ev->root.x;
7451    bd->mouse.current.my = ev->root.y;
7452    if (bd->bg_evas_in)
7453      {
7454         if (!((evas_event_down_count_get(bd->bg_evas) > 0) &&
7455               (!((ev->mode == ECORE_X_EVENT_MODE_GRAB) &&
7456                  (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)))))
7457           {
7458              if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7459                evas_event_feed_mouse_cancel(bd->bg_evas, ev->time, NULL);
7460              evas_event_feed_mouse_out(bd->bg_evas, ev->time, NULL);
7461              bd->bg_evas_in = EINA_FALSE;
7462           }
7463      }
7464    return ECORE_CALLBACK_PASS_ON;
7465 }
7466
7467 static Eina_Bool
7468 _e_border_cb_mouse_wheel(void    *data,
7469                          int type __UNUSED__,
7470                          void    *event)
7471 {
7472    Ecore_Event_Mouse_Wheel *ev;
7473    E_Border *bd;
7474
7475    ev = event;
7476    bd = data;
7477    if ((ev->event_window == bd->win) ||
7478        (ev->event_window == bd->event_win))
7479      {
7480         bd->mouse.current.mx = ev->root.x;
7481         bd->mouse.current.my = ev->root.y;
7482         if (!bd->cur_mouse_action)
7483           e_bindings_wheel_event_handle(E_BINDING_CONTEXT_WINDOW,
7484                                         E_OBJECT(bd), ev);
7485      }
7486    evas_event_feed_mouse_wheel(bd->bg_evas, ev->direction, ev->z, ev->timestamp, NULL);
7487    return ECORE_CALLBACK_PASS_ON;
7488 }
7489
7490 static Eina_Bool
7491 _e_border_cb_mouse_down(void    *data,
7492                         int type __UNUSED__,
7493                         void    *event)
7494 {
7495    Ecore_Event_Mouse_Button *ev;
7496    E_Border *bd;
7497
7498    ev = event;
7499    bd = data;
7500    if ((ev->event_window == bd->win) ||
7501        (ev->event_window == bd->event_win))
7502      {
7503         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7504           {
7505              bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7506              bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7507              bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7508              bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7509              bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7510              bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7511           }
7512         else
7513           {
7514              bd->moveinfo.down.x = bd->x + bd->fx.x;
7515              bd->moveinfo.down.y = bd->y + bd->fx.y;
7516              bd->moveinfo.down.w = bd->w;
7517              bd->moveinfo.down.h = bd->h;
7518           }
7519         bd->mouse.current.mx = ev->root.x;
7520         bd->mouse.current.my = ev->root.y;
7521         if (!bd->cur_mouse_action)
7522           {
7523              bd->cur_mouse_action =
7524                e_bindings_mouse_down_event_handle(E_BINDING_CONTEXT_WINDOW,
7525                                                   E_OBJECT(bd), ev);
7526              if (bd->cur_mouse_action)
7527                {
7528                   if ((!bd->cur_mouse_action->func.end_mouse) &&
7529                       (!bd->cur_mouse_action->func.end))
7530                     bd->cur_mouse_action = NULL;
7531                   if (bd->cur_mouse_action)
7532                     e_object_ref(E_OBJECT(bd->cur_mouse_action));
7533                }
7534           }
7535         e_focus_event_mouse_down(bd);
7536      }
7537    if (ev->window != ev->event_window)
7538      {
7539         return 1;
7540      }
7541    if ((ev->window != bd->event_win) && (ev->event_window != bd->win))
7542      {
7543         return 1;
7544      }
7545    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7546      {
7547         bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7548         bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7549         bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7550         bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7551         bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7552         bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7553      }
7554    else
7555      {
7556         bd->moveinfo.down.x = bd->x + bd->fx.x;
7557         bd->moveinfo.down.y = bd->y + bd->fx.y;
7558         bd->moveinfo.down.w = bd->w;
7559         bd->moveinfo.down.h = bd->h;
7560      }
7561    bd->mouse.current.mx = ev->root.x;
7562    bd->mouse.current.my = ev->root.y;
7563 /*
7564    if (bd->moving)
7565      {
7566      }
7567    else if (bd->resize_mode != RESIZE_NONE)
7568      {
7569      }
7570    else
7571  */
7572    {
7573       Evas_Button_Flags flags = EVAS_BUTTON_NONE;
7574
7575       if (ev->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
7576       if (ev->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
7577       evas_event_feed_mouse_down(bd->bg_evas, ev->buttons, flags, ev->timestamp, NULL);
7578    }
7579    return ECORE_CALLBACK_PASS_ON;
7580 }
7581
7582 static Eina_Bool
7583 _e_border_cb_mouse_up(void    *data,
7584                       int type __UNUSED__,
7585                       void    *event)
7586 {
7587    Ecore_Event_Mouse_Button *ev;
7588    E_Border *bd;
7589
7590    ev = event;
7591    bd = data;
7592    if ((ev->event_window == bd->win) ||
7593        (ev->event_window == bd->event_win))
7594      {
7595         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7596           {
7597              bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7598              bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7599              bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7600              bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7601           }
7602         bd->mouse.current.mx = ev->root.x;
7603         bd->mouse.current.my = ev->root.y;
7604         /* also we dont pass the same params that went in - then again that */
7605         /* should be ok as we are just ending the action if it has an end */
7606         if (bd->cur_mouse_action)
7607           {
7608              if (bd->cur_mouse_action->func.end_mouse)
7609                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", ev);
7610              else if (bd->cur_mouse_action->func.end)
7611                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
7612              e_object_unref(E_OBJECT(bd->cur_mouse_action));
7613              bd->cur_mouse_action = NULL;
7614           }
7615         else
7616           {
7617              if (!e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd), ev))
7618                e_focus_event_mouse_up(bd);
7619           }
7620      }
7621    if (ev->window != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7622    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7623      {
7624         bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7625         bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7626         bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7627         bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7628      }
7629    bd->mouse.current.mx = ev->root.x;
7630    bd->mouse.current.my = ev->root.y;
7631
7632    bd->drag.start = 0;
7633
7634    evas_event_feed_mouse_up(bd->bg_evas, ev->buttons, EVAS_BUTTON_NONE, ev->timestamp, NULL);
7635    return ECORE_CALLBACK_PASS_ON;
7636 }
7637
7638 static void
7639 _e_border_stay_within_container(E_Border *bd, int x, int y, int *new_x, int *new_y)
7640 {
7641 #ifdef _F_BORDER_CLIP_TO_ZONE_
7642    int new_x_max, new_y_max;
7643    int new_x_min, new_y_min;
7644    int margin_x, margin_y;
7645
7646    margin_x = bd->w - 100;
7647    margin_y = bd->h - 100;
7648
7649    new_x_max = bd->zone->x + bd->zone->w - bd->w + margin_x;
7650    new_x_min = bd->zone->x - margin_x;
7651    new_y_max = bd->zone->y + bd->zone->h - bd->h + margin_y;
7652    new_y_min = bd->zone->y - margin_y;
7653
7654    if (x >= new_x_max)      *new_x = new_x_max;
7655    else if (x <= new_x_min) *new_x = new_x_min;
7656
7657    if (y >= new_y_max)      *new_y = new_y_max;
7658    else if (y <= new_y_min) *new_y = new_y_min;
7659 #endif
7660 }
7661
7662 static Eina_Bool
7663 _e_border_cb_mouse_move(void    *data,
7664                         int type __UNUSED__,
7665                         void    *event)
7666 {
7667    Ecore_Event_Mouse_Move *ev;
7668    E_Border *bd;
7669
7670    ev = event;
7671    bd = data;
7672    if ((ev->window != bd->event_win) &&
7673        (ev->event_window != bd->win)) return ECORE_CALLBACK_PASS_ON;
7674    bd->mouse.current.mx = ev->root.x;
7675    bd->mouse.current.my = ev->root.y;
7676    if (bd->moving)
7677      {
7678         int x, y, new_x, new_y;
7679         int new_w, new_h;
7680         Eina_List *skiplist = NULL;
7681 #if 0
7682         // FIXME: remove? sync what for when only moving?
7683         if ((ecore_loop_time_get() - bd->client.netwm.sync.time) > 0.5)
7684           bd->client.netwm.sync.wait = 0;
7685         if ((bd->client.netwm.sync.request) &&
7686             (bd->client.netwm.sync.alarm) &&
7687             (bd->client.netwm.sync.wait > 1)) return ECORE_CALLBACK_PASS_ON;
7688 #endif
7689         if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
7690           {
7691              x = bd->mouse.last_down[bd->moveinfo.down.button - 1].x +
7692                (bd->mouse.current.mx - bd->moveinfo.down.mx);
7693              y = bd->mouse.last_down[bd->moveinfo.down.button - 1].y +
7694                (bd->mouse.current.my - bd->moveinfo.down.my);
7695           }
7696         else
7697           {
7698              x = bd->moveinfo.down.x +
7699                (bd->mouse.current.mx - bd->moveinfo.down.mx);
7700              y = bd->moveinfo.down.y +
7701                (bd->mouse.current.my - bd->moveinfo.down.my);
7702           }
7703         new_x = x;
7704         new_y = y;
7705
7706 #ifdef _F_USE_RESIST_MAGNETIC_EFFECT_
7707         skiplist = eina_list_append(skiplist, bd);
7708         e_resist_container_border_position(bd->zone->container, skiplist,
7709                                            bd->x, bd->y, bd->w, bd->h,
7710                                            x, y, bd->w, bd->h,
7711                                            &new_x, &new_y, &new_w, &new_h);
7712         eina_list_free(skiplist);
7713
7714         _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
7715 #else
7716         /* if (e_config->window_out_of_vscreen_limits_partly) */
7717         if (1)
7718           _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
7719         else
7720           {
7721              skiplist = eina_list_append(skiplist, bd);
7722              e_resist_container_border_position(bd->zone->container, skiplist,
7723                                                 bd->x, bd->y, bd->w, bd->h,
7724                                                 x, y, bd->w, bd->h,
7725                                                 &new_x, &new_y, &new_w, &new_h);
7726              eina_list_free(skiplist);
7727           }
7728 #endif
7729         bd->shelf_fix.x = 0;
7730         bd->shelf_fix.y = 0;
7731         bd->shelf_fix.modified = 0;
7732         e_border_move(bd, new_x, new_y);
7733         e_zone_flip_coords_handle(bd->zone, ev->root.x, ev->root.y);
7734      }
7735    else if (bd->resize_mode != RESIZE_NONE)
7736      {
7737         if ((bd->client.netwm.sync.request) &&
7738             (bd->client.netwm.sync.alarm))
7739           {
7740              if ((ecore_loop_time_get() - bd->client.netwm.sync.send_time) > 0.5)
7741                {
7742                   E_Border_Pending_Move_Resize *pnd;
7743
7744                   if (bd->pending_move_resize)
7745                     {
7746                        bd->changes.pos = 1;
7747                        bd->changes.size = 1;
7748                        bd->changed = 1;
7749                        _e_border_client_move_resize_send(bd);
7750                     }
7751                   EINA_LIST_FREE(bd->pending_move_resize, pnd)
7752                     E_FREE(pnd);
7753
7754                   bd->client.netwm.sync.wait = 0;
7755                }
7756              /* sync.wait is incremented when resize_handle sends
7757               * sync-request and decremented by sync-alarm cb. so
7758               * we resize here either on initial resize, timeout or
7759               * when no new resize-request was added by sync-alarm cb.
7760               */
7761              if (!bd->client.netwm.sync.wait)
7762                _e_border_resize_handle(bd);
7763           }
7764         else
7765           _e_border_resize_handle(bd);
7766      }
7767    else
7768      {
7769         if (bd->drag.start)
7770           {
7771              if ((bd->drag.x == -1) && (bd->drag.y == -1))
7772                {
7773                   bd->drag.x = ev->root.x;
7774                   bd->drag.y = ev->root.y;
7775                }
7776              else
7777                {
7778                   int dx, dy;
7779
7780                   dx = bd->drag.x - ev->root.x;
7781                   dy = bd->drag.y - ev->root.y;
7782                   if (((dx * dx) + (dy * dy)) >
7783                       (e_config->drag_resist * e_config->drag_resist))
7784                     {
7785      /* start drag! */
7786                         if (bd->icon_object)
7787                           {
7788                              Evas_Object *o = NULL;
7789                              Evas_Coord x, y, w, h;
7790                              const char *drag_types[] = { "enlightenment/border" };
7791
7792                              e_object_ref(E_OBJECT(bd));
7793                              evas_object_geometry_get(bd->icon_object,
7794                                                       &x, &y, &w, &h);
7795                              drag_border = e_drag_new(bd->zone->container,
7796                                                       bd->x + bd->fx.x + x,
7797                                                       bd->y + bd->fx.y + y,
7798                                                       drag_types, 1, bd, -1,
7799                                                       NULL,
7800                                                       _e_border_cb_drag_finished);
7801                              o = e_border_icon_add(bd, drag_border->evas);
7802                              if (!o)
7803                                {
7804      /* FIXME: fallback icon for drag */
7805                                    o = evas_object_rectangle_add(drag_border->evas);
7806                                    evas_object_color_set(o, 255, 255, 255, 255);
7807                                }
7808                              e_drag_object_set(drag_border, o);
7809
7810                              e_drag_resize(drag_border, w, h);
7811                              e_drag_start(drag_border, bd->drag.x, bd->drag.y);
7812                           }
7813                         bd->drag.start = 0;
7814                     }
7815                }
7816           }
7817         evas_event_feed_mouse_move(bd->bg_evas, ev->x, ev->y, ev->timestamp, NULL);
7818      }
7819    return ECORE_CALLBACK_PASS_ON;
7820 }
7821
7822 static Eina_Bool
7823 _e_border_cb_grab_replay(void *data __UNUSED__,
7824                          int        type,
7825                          void      *event)
7826 {
7827    Ecore_Event_Mouse_Button *ev;
7828
7829    if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
7830    ev = event;
7831    if ((e_config->pass_click_on)
7832        || (e_config->always_click_to_raise) // this works even if not on click-to-focus
7833        || (e_config->always_click_to_focus) // this works even if not on click-to-focus
7834       )
7835      {
7836         E_Border *bd;
7837
7838         bd = e_border_find_by_window(ev->event_window);
7839         if (bd)
7840           {
7841              if (bd->cur_mouse_action)
7842                return ECORE_CALLBACK_DONE;
7843              if (ev->event_window == bd->win)
7844                {
7845                   if (!e_bindings_mouse_down_find(E_BINDING_CONTEXT_WINDOW,
7846                                                   E_OBJECT(bd), ev, NULL))
7847                     return ECORE_CALLBACK_PASS_ON;
7848                }
7849           }
7850      }
7851    return ECORE_CALLBACK_DONE;
7852 }
7853
7854 static void
7855 _e_border_cb_drag_finished(E_Drag     *drag,
7856                            int dropped __UNUSED__)
7857 {
7858    E_Border *bd;
7859
7860    bd = drag->data;
7861    e_object_unref(E_OBJECT(bd));
7862    drag_border = NULL;
7863 }
7864
7865 #ifdef _F_USE_DESK_WINDOW_PROFILE_
7866 static Eina_Bool
7867 _e_border_cb_desk_window_profile_change(void *data  __UNUSED__,
7868                                         int ev_type __UNUSED__,
7869                                         void       *ev)
7870 {
7871    E_Event_Desk_Window_Profile_Change *e;
7872    Eina_List *l;
7873    E_Border *bd;
7874
7875    e = ev;
7876    EINA_LIST_FOREACH(borders, l, bd)
7877      {
7878         if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
7879           {
7880              bd->client.e.fetch.profile_list = 1;
7881              bd->changed = 1;
7882           }
7883      }
7884    return ECORE_CALLBACK_PASS_ON;
7885 }
7886 #endif
7887
7888 #ifdef _F_ZONE_WINDOW_ROTATION_
7889 static Eina_Bool
7890 _e_border_cb_zone_rotation_change_begin(void *data  __UNUSED__,
7891                                         int ev_type __UNUSED__,
7892                                         void       *ev)
7893 {
7894    E_Event_Zone_Rotation_Change_Begin *e = ev;
7895    Eina_Bool res = EINA_FALSE;
7896
7897    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
7898    if ((!e) || (!e->zone)) return ECORE_CALLBACK_PASS_ON;
7899
7900    res = _e_border_rotation_zone_check(e->zone);
7901    ELBF(ELBT_ROT, 0, e->zone->id, "ZONE ROT CHECK: result:%d (%d)", res, e->zone->rot.curr);
7902    if (res)
7903      {
7904         e_manager_comp_screen_lock(e_manager_current_get());
7905         res = _e_border_rotation_zone_vkbd_check(e->zone);
7906         ELBF(ELBT_ROT, 0, e->zone->id, "ZONE ROT CHECK: vkbd result:%d (%d)", res, e->zone->rot.curr);
7907         if (res)
7908           {
7909              res = _e_border_rotation_transient_for_check(rot.vkbd,
7910                                                           e->zone->rot.curr);
7911              ELBF(ELBT_ROT, 0, e->zone->id, "ZONE ROT CHECK: vkbd transient_for result:%d (%d)", res, e->zone->rot.curr);
7912           }
7913
7914         if (res)
7915           {
7916              if (rot.prepare_timer)
7917                ecore_timer_del(rot.prepare_timer);
7918              rot.prepare_timer = NULL;
7919
7920              if (rot.done_timer)
7921                ecore_timer_del(rot.done_timer);
7922              rot.done_timer = NULL;
7923
7924              ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win);
7925              ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
7926                                                            e->zone->rot.curr,
7927                                                            EINA_FALSE, 1, 1);
7928              rot.prepare_timer = ecore_timer_add(4.0f,
7929                                                  _e_border_rotation_change_prepare_timeout,
7930                                                  NULL);
7931              rot.wait_prepare_done = EINA_TRUE;
7932           }
7933         else
7934           _e_border_rotation_start(e->zone, EINA_TRUE);
7935      }
7936    else
7937      {
7938         /* there is no border which supports window manager rotation */
7939         e_zone_rotation_update_cancel(e->zone);
7940      }
7941    return ECORE_CALLBACK_PASS_ON;
7942 }
7943
7944 static Eina_Bool
7945 _e_border_rotation_change_prepare_timeout(void *data)
7946 {
7947    E_Zone *zone = data;
7948    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
7949
7950    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE_PREPARE", 0);
7951
7952    if ((!rot.wait_prepare_done) ||
7953        (!zone) ||
7954        (!_e_border_rotation_start(zone, EINA_FALSE)))
7955      {
7956         if (rot.prepare_timer)
7957           ecore_timer_del(rot.prepare_timer);
7958         rot.prepare_timer = NULL;
7959         rot.wait_prepare_done = EINA_FALSE;
7960      }
7961    return ECORE_CALLBACK_CANCEL;
7962 }
7963
7964 static void
7965 _e_border_rotation_change_request(E_Zone *zone __UNUSED__)
7966 {
7967    Eina_List *l = NULL;
7968    E_Border_Rotation_Info *info = NULL;
7969
7970    if (!e_config->wm_win_rotation) return;
7971    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
7972    rot.prepare_timer = NULL;
7973    rot.wait_prepare_done = EINA_FALSE;
7974
7975    EINA_LIST_FOREACH(rot.list, l, info)
7976      {
7977         if (!info->bd) continue;
7978         if ((zone->rot.block_count) &&
7979             (info->bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_DEPENDENT)) continue;
7980
7981         _e_border_event_border_rotation_change_begin_send(info->bd);
7982
7983         ELBF(ELBT_ROT, 1, info->bd->client.win,
7984              "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
7985              info->ang, info->win_resize, info->w, info->h);
7986
7987         ecore_x_e_window_rotation_change_prepare_send
7988           (info->bd->client.win, info->ang,
7989           info->win_resize, info->w, info->h);
7990
7991         if (!info->bd->client.e.state.rot.pending_change_request)
7992           {
7993              ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
7994              ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
7995                                                            info->ang);
7996           }
7997      }
7998
7999    if (rot.done_timer)
8000      ecore_timer_del(rot.done_timer);
8001    rot.done_timer = ecore_timer_add(4.0f,
8002                                     _e_border_rotation_change_done_timeout,
8003                                     NULL);
8004 }
8005
8006 EAPI void
8007 e_border_rotation_list_clear(E_Zone *zone, Eina_Bool send_request)
8008 {
8009    Eina_List *l = NULL;
8010    E_Border_Rotation_Info *info = NULL;
8011
8012    if (send_request) _e_border_rotation_change_request(zone);
8013    else
8014      {
8015         EINA_LIST_FREE(rot.list, info)
8016            E_FREE(info);
8017         rot.list = NULL;
8018      }
8019 }
8020
8021 static void
8022 _e_border_rotation_list_remove(E_Border *bd)
8023 {
8024    Eina_List *l = NULL;
8025    E_Border_Rotation_Info *info = NULL;
8026    E_Event_Border_Rotation_Change_End *ev = NULL;
8027    if (!e_config->wm_win_rotation) return;
8028
8029    EINA_LIST_FOREACH(rot.list, l, info)
8030      {
8031         if (info->bd == bd)
8032           {
8033              rot.list = eina_list_remove(rot.list, info);
8034              E_FREE(info);
8035           }
8036      }
8037
8038    if (bd->client.e.state.rot.wait_for_done)
8039      {
8040         bd->client.e.state.rot.wait_for_done = 0;
8041
8042         /* if we make the border event in the _e_border_free function,
8043          * then we may meet a crash problem, only work this at least e_border_hide.
8044          */
8045         if (!e_object_is_del(E_OBJECT(bd)))
8046           {
8047              ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
8048              if (ev)
8049                {
8050                   ev->border = bd;
8051                   e_object_ref(E_OBJECT(bd));
8052                   ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_END,
8053                                   ev,
8054                                   _e_border_event_border_rotation_change_end_free,
8055                                   NULL);
8056                }
8057           }
8058         if (eina_list_count(rot.list) == 0)
8059           {
8060              _e_border_rotation_change_done();
8061           }
8062      }
8063 }
8064
8065 static Eina_Bool
8066 _e_border_rotation_change_done_timeout(void *data __UNUSED__)
8067 {
8068    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8069    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE", 0);
8070    _e_border_rotation_change_done();
8071    return ECORE_CALLBACK_CANCEL;
8072 }
8073
8074 static void
8075 _e_border_rotation_change_done(void)
8076 {
8077    E_Manager *m = NULL;
8078    E_Border_Rotation_Info *info = NULL;
8079
8080    if (!e_config->wm_win_rotation) return;
8081
8082    if (rot.prepare_timer)
8083      ecore_timer_del(rot.prepare_timer);
8084    rot.prepare_timer = NULL;
8085
8086    rot.wait_prepare_done = EINA_FALSE;
8087
8088    if (rot.done_timer)
8089      ecore_timer_del(rot.done_timer);
8090    rot.done_timer = NULL;
8091
8092    EINA_LIST_FREE(rot.list, info)
8093      {
8094         if (info->bd)
8095           {
8096              info->bd->client.e.state.rot.wait_for_done = 0;
8097              ELB(ELBT_ROT, "TIMEOUT ROT_DONE", info->bd->client.win);
8098           }
8099         E_FREE(info);
8100      }
8101
8102    rot.list = NULL;
8103
8104    m = e_manager_current_get();
8105    e_manager_comp_screen_unlock(m);
8106    e_zone_rotation_update_done(e_util_zone_current_get(m));
8107 }
8108
8109 static int
8110 _prev_angle_get(Ecore_X_Window win)
8111 {
8112    int ret, count = 0, ang = -1;
8113    unsigned char* data = NULL;
8114
8115    ret = ecore_x_window_prop_property_get
8116       (win, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
8117       ECORE_X_ATOM_CARDINAL, 32, &data, &count);
8118
8119    if ((ret) && (data) && (count))
8120      ang = ((int *)data)[0];
8121    if (data) free(data);
8122    return ang;
8123 }
8124
8125 /* get proper rotation value using preferred rotation and list of available rotations */
8126 static int
8127 _e_border_rotation_get(E_Border *bd,
8128                        int       base_ang)
8129 {
8130    int ang = -1;
8131    int current_ang = bd->client.e.state.rot.curr;
8132    unsigned int i;
8133    Eina_Bool found = EINA_FALSE;
8134    Eina_Bool found_curr_ang = EINA_FALSE;
8135
8136    if (!e_config->wm_win_rotation) return ang;
8137    if (!bd->client.e.state.rot.app_set) return ang;
8138
8139    if (bd->client.e.state.rot.preferred_rot != -1)
8140      {
8141         ang = bd->client.e.state.rot.preferred_rot;
8142         ELBF(ELBT_ROT, 0, bd->client.win, "ang:%d base_ang:%d", ang, base_ang);
8143      }
8144    else if ((bd->client.e.state.rot.available_rots) &&
8145             (bd->client.e.state.rot.count))
8146      {
8147         for (i = 0; i < bd->client.e.state.rot.count; i++)
8148           {
8149              if (bd->client.e.state.rot.available_rots[i] == base_ang)
8150                {
8151                   ang = base_ang;
8152                   found = EINA_TRUE;
8153                   break;
8154                }
8155              if (bd->client.e.state.rot.available_rots[i] == current_ang)
8156                found_curr_ang = EINA_TRUE;
8157           }
8158
8159         /* do nothing. this window wants to maintain current state.
8160          * for example, window's available_rots: 0, 90, 270,
8161          * current zone rotation request: 180. the WM does nothing
8162          * for this window.
8163          */
8164         if (!found)
8165           {
8166              if ((bd->client.e.state.rot.curr != -1) && (found_curr_ang))
8167                ang = bd->client.e.state.rot.curr;
8168              else
8169                ang = bd->client.e.state.rot.available_rots[0];
8170           }
8171      }
8172    else
8173      {
8174         /* In this case, border doesn't have a list of
8175          * available rotations, thus WM should request
8176          * rotation with '0' degree to the application.
8177          */
8178         ang = 0;
8179      }
8180
8181    return ang;
8182 }
8183
8184 #define REGION_EQUAL_TO_ZONE(a, z) \
8185    ((((a)->x) == ((z)->x)) &&      \
8186     (((a)->y) == ((z)->y)) &&      \
8187     (((a)->w) == ((z)->w)) &&      \
8188     (((a)->h) == ((z)->h)))
8189
8190 static Eina_Bool
8191 _e_border_rotation_check(E_Border *bd)
8192 {
8193    E_Zone *zone = bd->zone;
8194    Eina_List *nl = NULL;
8195    int x, y, w, h, ang = 0;
8196    int _ang = 0;
8197    Eina_Bool resize = EINA_TRUE;
8198    Eina_Bool hint = EINA_FALSE;
8199    Eina_Bool move = EINA_TRUE;
8200
8201    if (!e_config->wm_win_rotation) return EINA_FALSE;
8202
8203    ELB(ELBT_ROT, "CHECK ROT", bd->client.win);
8204
8205    ang = zone->rot.curr;
8206
8207    if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
8208      {
8209         ELBF(ELBT_ROT, 1, bd->client.win,
8210              "%s->parent:0x%08x (support:%d app_set:%d ang:%d)",
8211              (rot.vkbd == bd) ? "vkbd" : "prediction",
8212              bd->parent ? bd->parent->client.win : 0,
8213              bd->parent ? bd->parent->client.e.state.rot.support : -1,
8214              bd->parent ? bd->parent->client.e.state.rot.app_set : -1,
8215              bd->parent ? bd->parent->client.e.state.rot.curr : -1);
8216
8217         if (bd->parent)
8218           {
8219              ang = bd->parent->client.e.state.rot.curr;
8220              if ((!bd->parent->client.e.state.rot.support) &&
8221                  (!bd->parent->client.e.state.rot.app_set))
8222                {
8223                   ang = 0;
8224                }
8225           }
8226      }
8227
8228    if ((!bd->client.e.state.rot.app_set) &&
8229        (!bd->client.e.state.rot.support))
8230      {
8231         /* hack for magnifier and keyboard popup */
8232         if ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER) ||
8233             (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP))
8234           {
8235              ELB(ELBT_BD, "MAG", bd->client.win);
8236              ang = 0;
8237              if ((rot.vkbd) && (rot.vkbd->visible))
8238                ang = rot.vkbd->client.e.state.rot.curr;
8239              hint = _e_border_rotation_geom_get(bd, zone, ang, &x, &y, &w, &h, &move);
8240              if (hint)
8241                {
8242                   ELBF(ELBT_ROT, 1, bd->client.win, "MAG %d,%d %dx%d m:%d", x, y, w, h, move);
8243                   _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
8244                }
8245              return EINA_FALSE;
8246           }
8247      }
8248
8249    if (bd->client.e.state.rot.app_set)
8250      {
8251         /* utility type window should be rotated according to
8252          * rotation of the transient_for window.
8253          */
8254         if ((bd->parent) &&
8255             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
8256           {
8257              ang = bd->parent->client.e.state.rot.curr;
8258              if ((!bd->parent->client.e.state.rot.support) &&
8259                  (!bd->parent->client.e.state.rot.app_set))
8260                {
8261                   /* if transient_for window doesn't support rotation feature,
8262                    * then this window should't be rotated.
8263                    * TODO: need to check whether window supports '0' degree or not.
8264                    */
8265                   ang = 0;
8266                   ELBF(ELBT_ROT, 0, bd->client.win,
8267                        "GET ROT ang:%d Transient_For:0x%08x Not support rot",
8268                        ang, bd->parent->client.win);
8269                }
8270              else
8271                {
8272                   ang = _e_border_rotation_get(bd->parent, ang);
8273                   ELBF(ELBT_ROT, 0, bd->client.win,
8274                        "GET ROT ang:%d Transient_For:0x%08x",
8275                        ang, bd->parent->client.win);
8276                }
8277           }
8278         else
8279           {
8280              ang = _e_border_rotation_get(bd, ang);
8281              ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d",
8282                   ang, bd->parent ? bd->parent->client.win : 0,
8283                   bd->client.netwm.type);
8284           }
8285      }
8286
8287    hint = _e_border_rotation_geom_get(bd, zone, ang, &x, &y, &w, &h, &move);
8288    if (hint)
8289      _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
8290
8291    /* need to check previous rotation angle, this may be because
8292     * the window was unmapped with non-0 rotation degree.
8293     * and now, the window wants to show on the 0 degree zone,
8294     * thus the wm should request to rotate the window to 0 degree.
8295     */
8296    if (!bd->visible)
8297      {
8298         _ang = _prev_angle_get(bd->client.win);
8299         if (_ang != -1)
8300           bd->client.e.state.rot.curr = _ang;
8301         ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang);
8302      }
8303
8304    if (bd->client.e.state.rot.curr != ang)
8305      {
8306         if ((rot.vkbd != bd) && (rot.vkbd_prediction != bd) &&
8307             /* check whether virtual keyboard is visible on the zone */
8308             (_e_border_rotation_zone_vkbd_check(bd->zone)) &&
8309             /* check whether virtual keyboard belongs to this border (transient_for) */
8310             (_e_border_rotation_vkbd_transient_for_check(bd)) &&
8311             /* check rotation of the virtual keyboard */
8312             (((rot.vkbd) && (rot.vkbd->client.e.state.rot.curr != ang)) ||
8313              ((rot.vkbd_prediction) && (rot.vkbd_prediction->client.e.state.rot.curr != ang))) &&
8314             (!rot.wait_prepare_done))
8315           {
8316              ELB(ELBT_ROT, "DO VKBD ROT", bd->client.win);
8317              e_manager_comp_screen_lock(e_manager_current_get());
8318
8319              if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8320              rot.prepare_timer = NULL;
8321
8322              if (rot.done_timer) ecore_timer_del(rot.done_timer);
8323              rot.done_timer = NULL;
8324
8325              ELB(ELBT_ROT, "send rot_change_prepare", rot.vkbd_ctrl_win);
8326              ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8327                                                            ang,
8328                                                            EINA_FALSE, 1, 1);
8329              rot.prepare_timer = ecore_timer_add(4.0f,
8330                                                  _e_border_rotation_change_prepare_timeout,
8331                                                  NULL);
8332              rot.wait_prepare_done = EINA_TRUE;
8333           }
8334
8335         bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8336         bd->client.e.state.rot.curr = ang;
8337         bd->client.e.state.rot.wait_for_done = 1;
8338         nl = eina_list_append(nl, bd);
8339
8340         e_border_rotation_list_add_change_req(zone, nl);
8341      }
8342    return EINA_TRUE;
8343 }
8344
8345 static Eina_Bool
8346 _e_border_rotation_zone_check(E_Zone *zone)
8347 {
8348    Eina_Bool wait = EINA_FALSE;
8349    E_Border_List *l = NULL;
8350    E_Border *bd = NULL;
8351
8352    if (!e_config->wm_win_rotation) return EINA_FALSE;
8353
8354    l = e_container_border_list_last(zone->container);
8355    if (!l) return EINA_FALSE;
8356    while ((bd = e_container_border_list_prev(l)))
8357      {
8358         if ((!bd) || (e_object_is_del(E_OBJECT(bd))) ||
8359             (!bd->visible) || (bd->zone != zone) ||
8360             (!E_INTERSECTS(zone->x, zone->y, zone->w, zone->h,
8361                            bd->x, bd->y, bd->w, bd->h))) continue;
8362
8363         if (((rot.vkbd) && (rot.vkbd == bd)) ||
8364             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)) ||
8365             ((REGION_EQUAL_TO_ZONE(bd, zone)) &&
8366              (bd->client.e.state.rot.preferred_rot != -1))) continue;
8367
8368         if (_e_border_rotation_border_check(bd, zone->rot.curr))
8369           {
8370              wait = EINA_TRUE;
8371              break;
8372           }
8373      }
8374    if (l) e_container_border_list_free(l);
8375
8376    return wait;
8377 }
8378
8379 // check if border is rotatable in ang.
8380 static Eina_Bool
8381 _e_border_rotation_border_check(E_Border *bd, int ang)
8382 {
8383    Eina_Bool wait = EINA_FALSE;
8384
8385    if (!bd) return wait;
8386
8387    if (((bd->client.e.state.rot.support) || (bd->client.e.state.rot.app_set)) &&
8388        /* basically WM allows only fullscreen window to rotate */
8389        ((REGION_EQUAL_TO_ZONE(bd, bd->zone)) ||
8390         /* we don't like this kind of code.
8391          * it means that the WM also allows non-fullscreen window to rotate if it sets geom hint.
8392          * such as large editable window.
8393          */
8394         ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE) && (bd->client.e.state.rot.geom_hint)) ||
8395         /* and floating mode window is also rotatable */
8396         (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) &&
8397        (bd->client.e.state.rot.preferred_rot == -1))
8398      {
8399         unsigned int i;
8400
8401         if (bd->client.e.state.rot.app_set)
8402           {
8403              if (bd->client.e.state.rot.available_rots &&
8404                  bd->client.e.state.rot.count)
8405                {
8406                   Eina_Bool found = EINA_FALSE;
8407                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8408                     {
8409                        if (bd->client.e.state.rot.available_rots[i] == ang)
8410                          {
8411                             found = EINA_TRUE;
8412                          }
8413                     }
8414                   if ((found) && (ang != bd->client.e.state.rot.curr))
8415                     {
8416                        wait = EINA_TRUE;
8417                     }
8418                   else
8419                     {
8420                        ELB(ELBT_ROT, "ROT CANCEL for preferred rot", bd->client.win);
8421                        wait = EINA_FALSE;
8422                     }
8423                }
8424           }
8425         else
8426           {
8427              ELB(ELBT_ROT, "DO ROT", 0);
8428              wait = EINA_TRUE;
8429           }
8430      }
8431
8432    return wait;
8433 }
8434
8435 /* check whether virtual keyboard is visible on the zone */
8436 static Eina_Bool
8437 _e_border_rotation_zone_vkbd_check(E_Zone *zone)
8438 {
8439    if (!e_config->wm_win_rotation) return EINA_FALSE;
8440
8441    if ((rot.vkbd_ctrl_win) &&
8442        (rot.vkbd) &&
8443        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8444        (rot.vkbd->visible) &&
8445        (rot.vkbd->zone == zone) &&
8446        (E_INTERSECTS(zone->x, zone->y,
8447                      zone->w, zone->h,
8448                      rot.vkbd->x, rot.vkbd->y,
8449                      rot.vkbd->w, rot.vkbd->h)))
8450      {
8451         return EINA_TRUE;
8452      }
8453    return EINA_FALSE;
8454 }
8455
8456 /* check whether border is parent of the virtual keyboard */
8457 static Eina_Bool
8458 _e_border_rotation_vkbd_transient_for_check(E_Border *bd)
8459 {
8460    if (!e_config->wm_win_rotation) return EINA_FALSE;
8461
8462    if (rot.vkbd_ctrl_win)
8463      {
8464         if ((rot.vkbd) && (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8465             (rot.vkbd != bd))
8466           {
8467              if (rot.vkbd->parent == bd)
8468                return EINA_TRUE;
8469           }
8470
8471         if ((rot.vkbd_prediction) && (!e_object_is_del(E_OBJECT(rot.vkbd_prediction))) &&
8472             (rot.vkbd_prediction != bd))
8473           {
8474              if (rot.vkbd_prediction == bd)
8475                return EINA_TRUE;
8476           }
8477      }
8478
8479    return EINA_FALSE;
8480 }
8481
8482 // check if bd's parent is rotatable.
8483 static Eina_Bool
8484 _e_border_rotation_transient_for_check(E_Border *bd, int ang)
8485 {
8486    Eina_Bool ret = EINA_FALSE;
8487
8488    if (!e_config->wm_win_rotation) return EINA_FALSE;
8489    if (!bd) return EINA_FALSE;
8490
8491    if (!bd->parent) ret = EINA_TRUE;
8492    else
8493      {
8494         if (_e_border_rotation_border_check(bd->parent, ang))
8495           ret = EINA_TRUE;
8496      }
8497
8498    return ret;
8499 }
8500
8501 EAPI Eina_Bool
8502 e_border_rotation_list_add_change_req(E_Zone *zone, Eina_List *list)
8503 {
8504    Eina_List *l;
8505    E_Border *bd;
8506    Eina_Bool ret = EINA_FALSE;
8507
8508    if (e_border_rotation_list_add(list))
8509      {
8510         EINA_LIST_FOREACH(list, l, bd)
8511            _e_border_hook_call(E_BORDER_HOOK_ROTATION_LIST_ADD, bd);
8512         _e_border_rotation_change_request(zone);
8513         ret = EINA_TRUE;
8514      }
8515
8516    return ret;
8517 }
8518
8519 EAPI Eina_Bool
8520 e_border_rotation_list_add(Eina_List *list)
8521 {
8522    Eina_List *l;
8523    E_Border *bd = NULL;
8524    E_Border_Rotation_Info *info = NULL;
8525
8526    if (!list) return EINA_FALSE;
8527    EINA_LIST_FOREACH(list, l, bd)
8528      {
8529         info = E_NEW(E_Border_Rotation_Info, 1);
8530         if (!info) continue;
8531
8532         info->bd = bd;
8533         info->ang = bd->client.e.state.rot.curr;
8534         info->x = bd->x; info->y = bd->y;
8535         info->w = bd->w; info->h = bd->h;
8536         info->win_resize = _e_border_rotation_pre_resize(bd);
8537         if (info->win_resize) bd->client.e.state.rot.pending_change_request = 1;
8538         rot.list = eina_list_append(rot.list, info);
8539      }
8540
8541    return EINA_TRUE;
8542 }
8543
8544 #define SIZE_EQUAL_TO_ZONE(a, z) \
8545    ((((a)->w) == ((z)->w)) &&    \
8546     (((a)->h) == ((z)->h)))
8547 static Eina_Bool
8548 _e_border_rotation_pre_resize(E_Border *bd)
8549 {
8550    E_Zone *zone = bd->zone;
8551    int ang = bd->client.e.state.rot.curr;
8552    int diff = ang - bd->client.e.state.rot.prev;
8553    int x, y, w, h;
8554    Eina_Bool move = EINA_FALSE;
8555    Eina_Bool hint = EINA_FALSE;
8556    Eina_Bool resize = EINA_FALSE;
8557
8558    if (SIZE_EQUAL_TO_ZONE(bd, zone)) return resize;
8559
8560    hint = _e_border_rotation_geom_get(bd, bd->zone, ang,
8561                                       &x, &y, &w, &h, &move);
8562    if (hint)
8563      {
8564         _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
8565         resize = EINA_TRUE;
8566      }
8567    else
8568      {
8569         x = bd->x; y = bd->y;
8570         w = bd->w; h = bd->h;
8571
8572         if ((diff != 180) && (diff != -180))
8573           {
8574              if (w != h)
8575                {
8576                   w = bd->h;
8577                   h = bd->w;
8578                   resize = EINA_TRUE;
8579
8580                   _e_border_move_resize_internal(bd, x, y, w, h,
8581                                                  EINA_TRUE, EINA_TRUE);
8582                }
8583           }
8584      }
8585
8586    return resize;
8587 }
8588
8589 static Eina_Bool
8590 _e_border_rotation_start(E_Zone *zone, Eina_Bool without_vkbd)
8591 {
8592    Eina_Bool wait = EINA_FALSE;
8593    E_Border_List *l = NULL;
8594    Eina_List *nl = NULL;
8595    E_Border *bd = NULL;
8596    E_Border_Rotation_Info *info = NULL;
8597
8598    if (!e_config->wm_win_rotation) return EINA_FALSE;
8599
8600    l = e_container_border_list_last(zone->container);
8601    if (!l) return EINA_FALSE;
8602    while ((bd = e_container_border_list_prev(l)))
8603      {
8604         if ((!bd) || (e_object_is_del(E_OBJECT(bd)))) continue;
8605
8606         if ((without_vkbd) &&
8607             (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE))
8608           {
8609              continue;
8610           }
8611
8612         if ((bd->visible) &&
8613             ((bd->client.e.state.rot.support) || (bd->client.e.state.rot.app_set)) &&
8614             (bd->zone == zone) &&
8615             (E_INTERSECTS(zone->x, zone->y, zone->w, zone->h,
8616                           bd->x, bd->y, bd->w, bd->h)))
8617           {
8618              if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue;
8619
8620              // check if this window is available to be rotate.
8621              if ((bd->client.e.state.rot.app_set) &&
8622                  (bd->client.e.state.rot.preferred_rot != -1)) continue;
8623
8624              /* check list of available rotations */
8625              int ang = zone->rot.curr;
8626              if (bd->client.e.state.rot.app_set)
8627                {
8628                   ang = _e_border_rotation_get(bd, ang);
8629                   ELBF(ELBT_ROT, 0, bd->client.win, "returned ang:%d", ang);
8630                }
8631
8632              /* skip same angle */
8633              if (bd->client.e.state.rot.curr == ang)
8634                {
8635                   /* FIXME: hack for rotating vkbd:
8636                    * even if angle of zone is not changed,
8637                    * if preferred_rot of parent is set with specific angle, vkbd has to rotate, too.
8638                    * all of other transient window like this case.
8639                    */
8640                   if ((bd->parent) &&
8641                       (bd->parent->client.e.state.rot.preferred_rot != -1))
8642                     ang = bd->parent->client.e.state.rot.preferred_rot;
8643                   if (bd->client.e.state.rot.curr == ang)
8644                     {
8645                        ELBF(ELBT_ROT, 0, bd->client.win, "SKIP ang:%d", ang);
8646                        continue;
8647                     }
8648                   ELBF(ELBT_ROT, 0, bd->client.win, "rotate by parent ang:%d", ang);
8649                }
8650              else
8651                {
8652                   ELBF(ELBT_ROT, 0, bd->client.win, "ADD ROT_LIST curr:%d != ang:%d",
8653                        bd->client.e.state.rot.curr, ang);
8654                }
8655
8656              bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8657              bd->client.e.state.rot.curr = ang;
8658              bd->client.e.state.rot.wait_for_done = 1;
8659              nl = eina_list_append(nl, bd);
8660
8661              /* check whether rotation is available for sub borders such as prediction and magnifier */
8662              Eina_List *ll;
8663              E_Border *_child;
8664              Eina_List *_list = _e_border_sub_borders_new(bd);
8665              EINA_LIST_FOREACH(_list, ll, _child)
8666                {
8667                   if ((_child->client.e.state.rot.support) ||
8668                       (_child->client.e.state.rot.app_set))
8669                     _e_border_rotation_check(_child);
8670                }
8671              eina_list_free(_list);
8672
8673              wait = EINA_TRUE;
8674           }
8675      }
8676
8677    if (l) e_container_border_list_free(l);
8678
8679    wait = e_border_rotation_list_add_change_req(zone, nl);
8680    eina_list_free(nl);
8681
8682    return wait;
8683 }
8684
8685 static Eina_Bool
8686 _e_border_cb_window_configure(void *data    __UNUSED__,
8687                               int   ev_type __UNUSED__,
8688                               void         *ev)
8689 {
8690    Ecore_X_Event_Window_Configure *e = ev;
8691    if (!e) return ECORE_CALLBACK_PASS_ON;
8692    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8693
8694    E_Border *bd = e_border_find_by_client_window(e->win);
8695    if (!bd) return ECORE_CALLBACK_PASS_ON;
8696
8697    if (bd->client.e.state.rot.pending_change_request)
8698      {
8699         if ((e->w == bd->w) && (e->h == bd->h))
8700           {
8701              ELBF(ELBT_ROT, 0, bd->client.win,
8702                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
8703                   bd->client.e.state.rot.curr,
8704                   bd->w, bd->h);
8705
8706              bd->client.e.state.rot.pending_change_request = 0;
8707
8708              ecore_x_e_window_rotation_change_request_send(bd->client.win,
8709                                                            bd->client.e.state.rot.curr);
8710           }
8711      }
8712    return ECORE_CALLBACK_PASS_ON;
8713 }
8714
8715 static Eina_Bool
8716 _e_border_rotation_geom_get(E_Border  *bd,
8717                             E_Zone    *zone,
8718                             int        ang,
8719                             int       *x,
8720                             int       *y,
8721                             int       *w,
8722                             int       *h,
8723                             Eina_Bool *move)
8724 {
8725    if (!e_config->wm_win_rotation) return EINA_FALSE;
8726
8727    Eina_Bool res = EINA_FALSE;
8728    Eina_Bool _move = EINA_TRUE;
8729    int _x = bd->x;
8730    int _y = bd->y;
8731    int _w = bd->w;
8732    int _h = bd->h;
8733
8734    if (x) *x = bd->x;
8735    if (y) *y = bd->y;
8736    if (w) *w = bd->w;
8737    if (h) *h = bd->h;
8738    if (move) *move = EINA_TRUE;
8739
8740    if (bd->client.e.state.rot.geom_hint)
8741      {
8742         switch (ang)
8743           {
8744            case   0:
8745               _w = bd->client.e.state.rot.geom[0].w;
8746               _h = bd->client.e.state.rot.geom[0].h;
8747               if (_w == 0) _w = bd->w;
8748               if (_h == 0) _h = bd->h;
8749               _x = 0; _y = zone->h - _h;
8750               break;
8751            case  90:
8752               _w = bd->client.e.state.rot.geom[1].w;
8753               _h = bd->client.e.state.rot.geom[1].h;
8754               if (_w == 0) _w = bd->w;
8755               if (_h == 0) _h = bd->h;
8756               _x = zone->w - _w; _y = 0;
8757               break;
8758            case 180:
8759               _w = bd->client.e.state.rot.geom[2].w;
8760               _h = bd->client.e.state.rot.geom[2].h;
8761               if (_w == 0) _w = bd->w;
8762               if (_h == 0) _h = bd->h;
8763               _x = 0; _y = 0;
8764               break;
8765            case 270:
8766               _w = bd->client.e.state.rot.geom[3].w;
8767               _h = bd->client.e.state.rot.geom[3].h;
8768               if (_w == 0) _w = bd->w;
8769               if (_h == 0) _h = bd->h;
8770               _x = 0; _y = 0;
8771               break;
8772           }
8773
8774         if (x) *x = _x;
8775         if (y) *y = _y;
8776         if (w) *w = _w;
8777         if (h) *h = _h;
8778
8779         if (!((rot.vkbd) && (rot.vkbd == bd)))
8780           {
8781              if (x) *x = bd->x;
8782              if (y) *y = bd->y;
8783              if (move) *move = EINA_FALSE;
8784           }
8785
8786         res = EINA_TRUE;
8787      }
8788
8789    if (res)
8790      {
8791         _x = 0; _y = 0; _w = 0; _h = 0;
8792         if (x) _x = *x;
8793         if (y) _y = *y;
8794         if (w) _w = *w;
8795         if (h) _h = *h;
8796         if (move) _move = *move;
8797
8798         ELBF(ELBT_ROT, 1, bd->client.win,
8799              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
8800              ang, _x, _y, _w, _h, _move);
8801      }
8802
8803    return res;
8804 }
8805 #endif
8806
8807 static Eina_Bool
8808 _e_border_post_move_resize_job(void *data)
8809 {
8810    E_Border *bd;
8811
8812    bd = (E_Border *)data;
8813    if (bd->post_move)
8814      {
8815         E_Border *tmp;
8816         Eina_List *l;
8817
8818         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
8819           ecore_x_window_move(tmp->win,
8820                               bd->x +
8821                               bd->client_inset.l +
8822                               bd->fx.x +
8823                               tmp->client.e.state.video_position.x,
8824                               bd->y +
8825                               bd->client_inset.t +
8826                               bd->fx.y +
8827                               tmp->client.e.state.video_position.y);
8828      }
8829    if (bd->client.e.state.video)
8830      {
8831         E_Border *parent;
8832
8833         parent = bd->client.e.state.video_parent_border;
8834         ecore_x_window_move(bd->win,
8835                             parent->x +
8836                             parent->client_inset.l +
8837                             parent->fx.x +
8838                             bd->client.e.state.video_position.x,
8839                             parent->y +
8840                             parent->client_inset.t +
8841                             parent->fx.y +
8842                             bd->client.e.state.video_position.y);
8843      }
8844    else if ((bd->post_move) && (bd->post_resize))
8845      {
8846         ecore_x_window_move_resize(bd->win,
8847                                    bd->x + bd->fx.x,
8848                                    bd->y + bd->fx.y,
8849                                    bd->w, bd->h);
8850      }
8851    else if (bd->post_move)
8852      {
8853         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
8854      }
8855    else if (bd->post_resize)
8856      {
8857         ecore_x_window_resize(bd->win, bd->w, bd->h);
8858      }
8859
8860    if (bd->client.e.state.video)
8861      {
8862         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
8863                 bd->win,
8864                 bd->client.e.state.video_parent_border->x +
8865                 bd->client.e.state.video_parent_border->client_inset.l +
8866                 bd->client.e.state.video_parent_border->fx.x +
8867                 bd->client.e.state.video_position.x,
8868                 bd->client.e.state.video_parent_border->y +
8869                 bd->client.e.state.video_parent_border->client_inset.t +
8870                 bd->client.e.state.video_parent_border->fx.y +
8871                 bd->client.e.state.video_position.y,
8872                 bd->w, bd->h);
8873      }
8874
8875    if (bd->post_show)
8876      {
8877         if (bd->visible)
8878           {
8879              bd->post_job = NULL;
8880              _e_border_show(bd);
8881           }
8882      }
8883    bd->post_show = 0;
8884    bd->post_move = 0;
8885    bd->post_resize = 0;
8886    bd->post_job = NULL;
8887    return ECORE_CALLBACK_CANCEL;
8888 }
8889
8890 static void
8891 _e_border_container_layout_hook(E_Container *con)
8892 {
8893    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
8894 }
8895
8896 static void
8897 _e_border_eval0(E_Border *bd)
8898 {
8899    int change_urgent = 0;
8900    int rem_change = 0;
8901 #ifdef _F_USE_DESK_WINDOW_PROFILE_
8902    Eina_Bool need_desk_set = EINA_FALSE;
8903 #endif
8904 #ifdef _F_ZONE_WINDOW_ROTATION_
8905    Eina_Bool need_rotation_set = EINA_FALSE;
8906
8907    if ((e_config->wm_win_rotation) &&
8908        (bd->client.icccm.fetch.transient_for))
8909      {
8910         if (((rot.vkbd) && (rot.vkbd == bd)) ||
8911             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
8912           {
8913              need_rotation_set = EINA_TRUE;
8914              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
8915           }
8916      }
8917 #endif
8918
8919    if (e_object_is_del(E_OBJECT(bd)))
8920      {
8921         CRI("_e_border_eval(%p) with deleted border!\n", bd);
8922         bd->changed = 0;
8923         return;
8924      }
8925
8926    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
8927
8928    bd->changes.border = 0;
8929
8930    /* fetch any info queued to be fetched */
8931    if (bd->client.netwm.fetch.state)
8932      {
8933         e_hints_window_state_get(bd);
8934         bd->client.netwm.fetch.state = 0;
8935         rem_change = 1;
8936      }
8937    if (bd->client.icccm.fetch.client_leader)
8938      {
8939         /* TODO: What do to if the client leader isn't mapped yet? */
8940         E_Border *bd_leader = NULL;
8941
8942         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
8943         if (bd->client.icccm.client_leader)
8944           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
8945         if (bd->leader)
8946           {
8947              if (bd->leader != bd_leader)
8948                {
8949                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
8950                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
8951                   bd->leader = NULL;
8952                }
8953              else
8954                bd_leader = NULL;
8955           }
8956         /* If this border is the leader of the group, don't register itself */
8957         if ((bd_leader) && (bd_leader != bd))
8958           {
8959              bd_leader->group = eina_list_append(bd_leader->group, bd);
8960              bd->leader = bd_leader;
8961              /* Only set the window modal to the leader it there is no parent */
8962              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
8963                  ((!bd->parent) || (bd->parent->modal != bd)))
8964                {
8965                   bd->leader->modal = bd;
8966                   if (bd->leader->focused)
8967                     e_border_focus_set(bd, 1, 1);
8968                   else
8969                     {
8970                        Eina_List *l;
8971                        E_Border *child;
8972
8973                        EINA_LIST_FOREACH(bd->leader->group, l, child)
8974                          {
8975                             if ((child != bd) && (child->focused))
8976                               e_border_focus_set(bd, 1, 1);
8977                          }
8978                     }
8979                }
8980           }
8981         bd->client.icccm.fetch.client_leader = 0;
8982         rem_change = 1;
8983      }
8984    if (bd->client.icccm.fetch.title)
8985      {
8986         char *title = ecore_x_icccm_title_get(bd->client.win);
8987         eina_stringshare_replace(&bd->client.icccm.title, title);
8988         if (title) free(title);
8989
8990         if (bd->bg_object)
8991           edje_object_part_text_set(bd->bg_object, "e.text.title",
8992                                     bd->client.icccm.title);
8993         bd->client.icccm.fetch.title = 0;
8994         rem_change = 1;
8995      }
8996    if (bd->client.netwm.fetch.name)
8997      {
8998         char *name;
8999         ecore_x_netwm_name_get(bd->client.win, &name);
9000         eina_stringshare_replace(&bd->client.netwm.name, name);
9001         if (name) free(name);
9002
9003         if (bd->bg_object)
9004           edje_object_part_text_set(bd->bg_object, "e.text.title",
9005                                     bd->client.netwm.name);
9006         bd->client.netwm.fetch.name = 0;
9007         rem_change = 1;
9008      }
9009    if (bd->client.icccm.fetch.name_class)
9010      {
9011         const char *pname, *pclass;
9012         char *nname, *nclass;
9013
9014         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
9015         pname = bd->client.icccm.name;
9016         pclass = bd->client.icccm.class;
9017         bd->client.icccm.name = eina_stringshare_add(nname);
9018         bd->client.icccm.class = eina_stringshare_add(nclass);
9019         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
9020           e_bindings_mapping_change_enable(EINA_FALSE);
9021 #ifdef _F_ZONE_WINDOW_ROTATION_
9022         if (e_config->wm_win_rotation)
9023           {
9024              if ((bd->client.icccm.name) && (bd->client.icccm.class))
9025                {
9026                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
9027                       (!strcmp(bd->client.icccm.class, "ISF")))
9028                     {
9029                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
9030                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
9031                        rot.vkbd = bd;
9032                     }
9033                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
9034                            (!strcmp(bd->client.icccm.class, "ISF")))
9035                     {
9036                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
9037                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
9038                        rot.vkbd_prediction = bd;
9039                     }
9040                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
9041                            (!strcmp(bd->client.icccm.class, "ISF")))
9042                     {
9043                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
9044                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
9045                     }
9046                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
9047                            (!strcmp(bd->client.icccm.class, "ISF")))
9048                     {
9049                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
9050                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
9051                     }
9052                }
9053           }
9054 #endif
9055         if (nname) free(nname);
9056         if (nclass) free(nclass);
9057
9058         if (!((bd->client.icccm.name == pname) &&
9059               (bd->client.icccm.class == pclass)))
9060           bd->changes.icon = 1;
9061
9062         if (pname) eina_stringshare_del(pname);
9063         if (pclass) eina_stringshare_del(pclass);
9064         bd->client.icccm.fetch.name_class = 0;
9065         bd->changes.icon = 1;
9066         rem_change = 1;
9067      }
9068    if (bd->client.icccm.fetch.state)
9069      {
9070         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
9071         bd->client.icccm.fetch.state = 0;
9072         rem_change = 1;
9073      }
9074    if (bd->client.e.fetch.state)
9075      {
9076         e_hints_window_e_state_get(bd);
9077         bd->client.e.fetch.state = 0;
9078         rem_change = 1;
9079      }
9080 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9081    if (bd->client.e.fetch.profile_list)
9082      {
9083         const char **profiles = NULL;
9084         const char *str;
9085         int num = 0, i;
9086
9087         if (bd->client.e.state.profile)
9088           eina_stringshare_del(bd->client.e.state.profile);
9089         EINA_LIST_FREE(bd->client.e.state.profiles, str)
9090           {
9091              if (str) eina_stringshare_del(str);
9092           }
9093         bd->client.e.state.profile = NULL;
9094         bd->client.e.state.profiles = NULL;
9095         bd->client.e.state.profile_list = 0;
9096
9097         if (ecore_x_e_window_profile_list_get(bd->client.win,
9098                                               &profiles, &num))
9099           {
9100              bd->client.e.state.profile_list = 1;
9101              for (i = 0; i < num; i++)
9102                {
9103                   str = eina_stringshare_add(profiles[i]);
9104                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
9105                }
9106
9107              /* We should set desk to contain given border after creating E_BORDER_ADD event.
9108               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
9109               */
9110              need_desk_set = EINA_TRUE;
9111           }
9112         else
9113           {
9114              if (strcmp(bd->desk->window_profile,
9115                         e_config->desktop_default_window_profile) != 0)
9116                {
9117                   ecore_x_e_window_profile_set(bd->client.win,
9118                                                bd->desk->window_profile);
9119                }
9120           }
9121
9122         if (profiles)
9123           {
9124              for (i = 0; i < num; i++)
9125                 if (profiles[i]) free(profiles[i]);
9126              free(profiles);
9127           }
9128
9129         bd->client.e.fetch.profile_list = 0;
9130      }
9131 #endif
9132 #ifdef _F_ZONE_WINDOW_ROTATION_
9133    if ((e_config->wm_win_rotation) &&
9134        (bd->client.e.fetch.rot.support))
9135      {
9136         int ret = 0;
9137         unsigned int support = 0;
9138
9139         ret = ecore_x_window_prop_card32_get
9140           (bd->client.win,
9141           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
9142           &support, 1);
9143
9144         bd->client.e.state.rot.support = 0;
9145         if ((ret == 1) && (support == 1))
9146           bd->client.e.state.rot.support = 1;
9147
9148         if (bd->client.e.state.rot.support)
9149           need_rotation_set = EINA_TRUE;
9150
9151         bd->client.e.fetch.rot.support = 0;
9152      }
9153    if ((e_config->wm_win_rotation) &&
9154        (bd->client.e.fetch.rot.geom_hint))
9155      {
9156         Eina_Rectangle r[4];
9157         int i, x, y, w, h;
9158         bd->client.e.state.rot.geom_hint = 0;
9159         for (i = 0; i < 4; i++)
9160           {
9161              r[i].x = bd->client.e.state.rot.geom[i].x;
9162              r[i].y = bd->client.e.state.rot.geom[i].y;
9163              r[i].w = bd->client.e.state.rot.geom[i].w;
9164              r[i].h = bd->client.e.state.rot.geom[i].h;
9165
9166              bd->client.e.state.rot.geom[i].x = 0;
9167              bd->client.e.state.rot.geom[i].y = 0;
9168              bd->client.e.state.rot.geom[i].w = 0;
9169              bd->client.e.state.rot.geom[i].h = 0;
9170           }
9171
9172         for (i = 0; i < 4; i++)
9173           {
9174              x = 0; y = 0; w = 0; h = 0;
9175              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
9176                {
9177                   bd->client.e.state.rot.geom_hint = 1;
9178                   bd->client.e.state.rot.geom[i].x = x;
9179                   bd->client.e.state.rot.geom[i].y = y;
9180                   bd->client.e.state.rot.geom[i].w = w;
9181                   bd->client.e.state.rot.geom[i].h = h;
9182
9183                   if (!((r[i].x == x) && (r[i].y == y) &&
9184                         (r[i].w == w) && (r[i].h == h)))
9185                     {
9186                        need_rotation_set = EINA_TRUE;
9187                     }
9188                }
9189           }
9190         bd->client.e.fetch.rot.geom_hint = 0;
9191      }
9192    if ((e_config->wm_win_rotation) &&
9193        (bd->client.e.fetch.rot.app_set))
9194      {
9195         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
9196         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
9197         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
9198
9199         if (_prev_app_set != bd->client.e.state.rot.app_set)
9200           need_rotation_set = EINA_TRUE;
9201
9202         bd->client.e.fetch.rot.app_set = 0;
9203      }
9204    if ((e_config->wm_win_rotation) &&
9205        (bd->client.e.fetch.rot.preferred_rot))
9206      {
9207         int r = 0, _prev_preferred_rot;
9208         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
9209         bd->client.e.state.rot.preferred_rot = -1;
9210         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
9211           {
9212              bd->client.e.state.rot.preferred_rot = r;
9213              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
9214           }
9215         else
9216           {
9217              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
9218           }
9219
9220         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
9221           need_rotation_set = EINA_TRUE;
9222
9223         bd->client.e.fetch.rot.preferred_rot = 0;
9224      }
9225    if ((e_config->wm_win_rotation) &&
9226        (bd->client.e.fetch.rot.available_rots))
9227      {
9228         Eina_Bool res, diff = EINA_FALSE;
9229         int *rots = NULL;
9230         unsigned int count = 0, i = 0;
9231         int _prev_rots[4] = { -1, };
9232
9233         if (bd->client.e.state.rot.available_rots)
9234           {
9235              memcpy(_prev_rots,
9236                     bd->client.e.state.rot.available_rots,
9237                     (sizeof(int) * bd->client.e.state.rot.count));
9238
9239              E_FREE(bd->client.e.state.rot.available_rots);
9240           }
9241
9242         bd->client.e.state.rot.count = 0;
9243
9244         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
9245                                                                 &rots, &count);
9246         if ((res) && (count > 0) && (rots))
9247           {
9248              bd->client.e.state.rot.available_rots = rots;
9249              bd->client.e.state.rot.count = count;
9250
9251              for (i = 0; i < count; i++)
9252                {
9253                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
9254                   if ((!diff) && (_prev_rots[i] != rots[i]))
9255                     {
9256                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
9257                             count, i, _prev_rots[i], rots[i]);
9258                        diff = EINA_TRUE;
9259                     }
9260                }
9261           }
9262         else
9263           {
9264              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9265              diff = EINA_TRUE;
9266           }
9267
9268         if (diff) need_rotation_set = EINA_TRUE;
9269         bd->client.e.fetch.rot.available_rots = 0;
9270      }
9271 #endif
9272    if (bd->client.netwm.fetch.type)
9273      {
9274         e_hints_window_type_get(bd);
9275         if ((!bd->lock_border) || (!bd->client.border.name))
9276           bd->client.border.changed = 1;
9277
9278         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9279           {
9280              if (!bd->client.netwm.state.skip_pager)
9281                {
9282                   bd->client.netwm.state.skip_pager = 1;
9283                   bd->client.netwm.update.state = 1;
9284                }
9285              if (!bd->client.netwm.state.skip_taskbar)
9286                {
9287                   bd->client.netwm.state.skip_taskbar = 1;
9288                   bd->client.netwm.update.state = 1;
9289                }
9290           }
9291         bd->client.netwm.fetch.type = 0;
9292      }
9293    if (bd->client.icccm.fetch.machine)
9294      {
9295         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9296
9297         if ((!machine) && (bd->client.icccm.client_leader))
9298           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9299
9300         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9301         if (machine) free(machine);
9302
9303         bd->client.icccm.fetch.machine = 0;
9304         rem_change = 1;
9305      }
9306    if (bd->client.icccm.fetch.command)
9307      {
9308         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9309           {
9310              int i;
9311
9312              for (i = 0; i < bd->client.icccm.command.argc; i++)
9313                free(bd->client.icccm.command.argv[i]);
9314              free(bd->client.icccm.command.argv);
9315           }
9316         bd->client.icccm.command.argc = 0;
9317         bd->client.icccm.command.argv = NULL;
9318         ecore_x_icccm_command_get(bd->client.win,
9319                                   &(bd->client.icccm.command.argc),
9320                                   &(bd->client.icccm.command.argv));
9321         if ((bd->client.icccm.client_leader) &&
9322             (!bd->client.icccm.command.argv))
9323           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9324                                     &(bd->client.icccm.command.argc),
9325                                     &(bd->client.icccm.command.argv));
9326         bd->client.icccm.fetch.command = 0;
9327         rem_change = 1;
9328      }
9329    if (bd->client.icccm.fetch.hints)
9330      {
9331         Eina_Bool accepts_focus, is_urgent;
9332
9333         accepts_focus = EINA_TRUE;
9334         is_urgent = EINA_FALSE;
9335         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9336         if (ecore_x_icccm_hints_get(bd->client.win,
9337                                     &accepts_focus,
9338                                     &bd->client.icccm.initial_state,
9339                                     &bd->client.icccm.icon_pixmap,
9340                                     &bd->client.icccm.icon_mask,
9341                                     &bd->client.icccm.icon_window,
9342                                     &bd->client.icccm.window_group,
9343                                     &is_urgent))
9344           {
9345              bd->client.icccm.accepts_focus = accepts_focus;
9346              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9347                change_urgent = 1;
9348              bd->client.icccm.urgent = is_urgent;
9349
9350              /* If this is a new window, set the state as requested. */
9351              if ((bd->new_client) &&
9352                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9353                {
9354                   e_border_iconify(bd);
9355                   e_border_hide(bd, 1);
9356                }
9357           }
9358         bd->client.icccm.fetch.hints = 0;
9359         rem_change = 1;
9360      }
9361    if (bd->client.icccm.fetch.size_pos_hints)
9362      {
9363         Eina_Bool request_pos;
9364
9365         request_pos = EINA_FALSE;
9366         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9367                                              &request_pos,
9368                                              &bd->client.icccm.gravity,
9369                                              &bd->client.icccm.min_w,
9370                                              &bd->client.icccm.min_h,
9371                                              &bd->client.icccm.max_w,
9372                                              &bd->client.icccm.max_h,
9373                                              &bd->client.icccm.base_w,
9374                                              &bd->client.icccm.base_h,
9375                                              &bd->client.icccm.step_w,
9376                                              &bd->client.icccm.step_h,
9377                                              &bd->client.icccm.min_aspect,
9378                                              &bd->client.icccm.max_aspect))
9379           {
9380              bd->client.icccm.request_pos = request_pos;
9381           }
9382         else
9383           {
9384           }
9385         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9386         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9387         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9388         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9389         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9390         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9391         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9392         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9393         // if doing a resize, fix it up
9394         if (bd->resize_mode != RESIZE_NONE)
9395           {
9396              int x, y, w, h, new_w, new_h;
9397
9398              x = bd->x;
9399              y = bd->y;
9400              w = bd->w;
9401              h = bd->h;
9402              new_w = w;
9403              new_h = h;
9404              e_border_resize_limit(bd, &new_w, &new_h);
9405              if ((bd->resize_mode == RESIZE_TL) ||
9406                  (bd->resize_mode == RESIZE_L) ||
9407                  (bd->resize_mode == RESIZE_BL))
9408                x += (w - new_w);
9409              if ((bd->resize_mode == RESIZE_TL) ||
9410                  (bd->resize_mode == RESIZE_T) ||
9411                  (bd->resize_mode == RESIZE_TR))
9412                y += (h - new_h);
9413              e_border_move_resize(bd, x, y, new_w, new_h);
9414           }
9415         bd->client.icccm.fetch.size_pos_hints = 0;
9416         rem_change = 1;
9417      }
9418    if (bd->client.icccm.fetch.protocol)
9419      {
9420         int i, num;
9421         Ecore_X_WM_Protocol *proto;
9422
9423         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9424         if (proto)
9425           {
9426              for (i = 0; i < num; i++)
9427                {
9428                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9429                     bd->client.icccm.delete_request = 1;
9430                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9431                     bd->client.icccm.take_focus = 1;
9432                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9433                     bd->client.netwm.ping = 1;
9434                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9435                     {
9436                        bd->client.netwm.sync.request = 1;
9437                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9438                                                            &bd->client.netwm.sync.counter))
9439                          bd->client.netwm.sync.request = 0;
9440                     }
9441                }
9442              free(proto);
9443           }
9444         if (bd->client.netwm.ping)
9445           e_border_ping(bd);
9446         else
9447           {
9448              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9449              bd->ping_poller = NULL;
9450           }
9451         bd->client.icccm.fetch.protocol = 0;
9452      }
9453    if (bd->client.icccm.fetch.transient_for)
9454      {
9455         /* TODO: What do to if the transient for isn't mapped yet? */
9456         E_Border *bd_parent = NULL;
9457 #ifdef _F_DEICONIFY_APPROVE_
9458         Eina_Bool change_parent = EINA_FALSE;
9459 #endif
9460
9461         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9462         if (bd->client.icccm.transient_for)
9463           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9464         /* If we already have a parent, remove it */
9465         if (bd->parent)
9466           {
9467              if (bd_parent != bd->parent)
9468                {
9469                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9470                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9471                   bd->parent = NULL;
9472                }
9473              else
9474                bd_parent = NULL;
9475           }
9476         if ((bd_parent) && (bd_parent != bd) &&
9477             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9478           {
9479              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9480              bd->parent = bd_parent;
9481 #ifdef _F_DEICONIFY_APPROVE_
9482              change_parent = EINA_TRUE;
9483 #endif
9484           }
9485         if (bd->parent)
9486           {
9487              e_border_layer_set(bd, bd->parent->layer);
9488              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9489                {
9490                   Ecore_X_Window_Attributes attr;
9491                   bd->parent->modal = bd;
9492                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9493                   bd->parent->saved.event_mask = attr.event_mask.mine;
9494                   bd->parent->lock_close = 1;
9495                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9496                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9497                }
9498
9499              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9500                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9501                bd->take_focus = 1;
9502           }
9503
9504 #ifdef _F_DEICONIFY_APPROVE_
9505         if (change_parent)
9506           {
9507              bd->client.e.state.deiconify_approve.render_done = 0;
9508
9509              E_Border *ancestor_bd;
9510              ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
9511              if ((ancestor_bd) &&
9512                  (!e_object_is_del(E_OBJECT(ancestor_bd))))
9513                {
9514                   ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
9515                   bd->client.e.state.deiconify_approve.ancestor = NULL;
9516
9517                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
9518                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
9519                     {
9520                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
9521                          {
9522                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
9523                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
9524                             e_border_uniconify(ancestor_bd);
9525                          }
9526                     }
9527                }
9528           }
9529 #endif
9530         bd->client.icccm.fetch.transient_for = 0;
9531         rem_change = 1;
9532      }
9533    if (bd->client.icccm.fetch.window_role)
9534      {
9535         char *role = ecore_x_icccm_window_role_get(bd->client.win);
9536         eina_stringshare_replace(&bd->client.icccm.window_role, role);
9537         if (role) free(role);
9538
9539         bd->client.icccm.fetch.window_role = 0;
9540         rem_change = 1;
9541      }
9542    if (bd->client.icccm.fetch.icon_name)
9543      {
9544         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
9545         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
9546         if (icon_name) free(icon_name);
9547
9548         bd->client.icccm.fetch.icon_name = 0;
9549         rem_change = 1;
9550      }
9551    if (bd->client.netwm.fetch.icon_name)
9552      {
9553         char *icon_name;
9554         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
9555         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
9556         if (icon_name) free(icon_name);
9557
9558         bd->client.netwm.fetch.icon_name = 0;
9559         rem_change = 1;
9560      }
9561    if (bd->client.netwm.fetch.icon)
9562      {
9563         int i;
9564         if (bd->client.netwm.icons)
9565           {
9566              for (i = 0; i < bd->client.netwm.num_icons; i++)
9567                {
9568                   free(bd->client.netwm.icons[i].data);
9569                   bd->client.netwm.icons[i].data = NULL;
9570                }
9571              free(bd->client.netwm.icons);
9572           }
9573         bd->client.netwm.icons = NULL;
9574         bd->client.netwm.num_icons = 0;
9575         if (ecore_x_netwm_icons_get(bd->client.win,
9576                                      &bd->client.netwm.icons,
9577                                      &bd->client.netwm.num_icons))
9578           {
9579              // unless the rest of e17 uses border icons OTHER than icon #0
9580              // then free the rest that we don't need anymore.
9581              for (i = 1; i < bd->client.netwm.num_icons; i++)
9582                {
9583                   free(bd->client.netwm.icons[i].data);
9584                   bd->client.netwm.icons[i].data = NULL;
9585                }
9586              bd->client.netwm.num_icons = 1;
9587              bd->changes.icon = 1;
9588           }
9589         bd->client.netwm.fetch.icon = 0;
9590      }
9591    if (bd->client.netwm.fetch.user_time)
9592      {
9593         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
9594         bd->client.netwm.fetch.user_time = 0;
9595      }
9596    if (bd->client.netwm.fetch.strut)
9597      {
9598         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
9599                                              &bd->client.netwm.strut.left,
9600                                              &bd->client.netwm.strut.right,
9601                                              &bd->client.netwm.strut.top,
9602                                              &bd->client.netwm.strut.bottom,
9603                                              &bd->client.netwm.strut.left_start_y,
9604                                              &bd->client.netwm.strut.left_end_y,
9605                                              &bd->client.netwm.strut.right_start_y,
9606                                              &bd->client.netwm.strut.right_end_y,
9607                                              &bd->client.netwm.strut.top_start_x,
9608                                              &bd->client.netwm.strut.top_end_x,
9609                                              &bd->client.netwm.strut.bottom_start_x,
9610                                              &bd->client.netwm.strut.bottom_end_x))
9611           {
9612              ecore_x_netwm_strut_get(bd->client.win,
9613                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
9614                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
9615
9616              bd->client.netwm.strut.left_start_y = 0;
9617              bd->client.netwm.strut.left_end_y = 0;
9618              bd->client.netwm.strut.right_start_y = 0;
9619              bd->client.netwm.strut.right_end_y = 0;
9620              bd->client.netwm.strut.top_start_x = 0;
9621              bd->client.netwm.strut.top_end_x = 0;
9622              bd->client.netwm.strut.bottom_start_x = 0;
9623              bd->client.netwm.strut.bottom_end_x = 0;
9624           }
9625         bd->client.netwm.fetch.strut = 0;
9626      }
9627    if (bd->client.qtopia.fetch.soft_menu)
9628      {
9629         e_hints_window_qtopia_soft_menu_get(bd);
9630         bd->client.qtopia.fetch.soft_menu = 0;
9631         rem_change = 1;
9632      }
9633    if (bd->client.qtopia.fetch.soft_menus)
9634      {
9635         e_hints_window_qtopia_soft_menus_get(bd);
9636         bd->client.qtopia.fetch.soft_menus = 0;
9637         rem_change = 1;
9638      }
9639    if (bd->client.vkbd.fetch.state)
9640      {
9641         e_hints_window_virtual_keyboard_state_get(bd);
9642         bd->client.vkbd.fetch.state = 0;
9643         rem_change = 1;
9644      }
9645    if (bd->client.vkbd.fetch.vkbd)
9646      {
9647         e_hints_window_virtual_keyboard_get(bd);
9648         bd->client.vkbd.fetch.vkbd = 0;
9649         rem_change = 1;
9650      }
9651    if (bd->client.illume.conformant.fetch.conformant)
9652      {
9653         bd->client.illume.conformant.conformant =
9654           ecore_x_e_illume_conformant_get(bd->client.win);
9655         bd->client.illume.conformant.fetch.conformant = 0;
9656      }
9657    if (bd->client.illume.quickpanel.fetch.state)
9658      {
9659         bd->client.illume.quickpanel.state =
9660           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
9661         bd->client.illume.quickpanel.fetch.state = 0;
9662      }
9663    if (bd->client.illume.quickpanel.fetch.quickpanel)
9664      {
9665         bd->client.illume.quickpanel.quickpanel =
9666           ecore_x_e_illume_quickpanel_get(bd->client.win);
9667         bd->client.illume.quickpanel.fetch.quickpanel = 0;
9668      }
9669    if (bd->client.illume.quickpanel.fetch.priority.major)
9670      {
9671         bd->client.illume.quickpanel.priority.major =
9672           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
9673         bd->client.illume.quickpanel.fetch.priority.major = 0;
9674      }
9675    if (bd->client.illume.quickpanel.fetch.priority.minor)
9676      {
9677         bd->client.illume.quickpanel.priority.minor =
9678           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
9679         bd->client.illume.quickpanel.fetch.priority.minor = 0;
9680      }
9681    if (bd->client.illume.quickpanel.fetch.zone)
9682      {
9683         bd->client.illume.quickpanel.zone =
9684           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
9685         bd->client.illume.quickpanel.fetch.zone = 0;
9686      }
9687    if (bd->client.illume.drag.fetch.drag)
9688      {
9689         bd->client.illume.drag.drag =
9690           ecore_x_e_illume_drag_get(bd->client.win);
9691         bd->client.illume.drag.fetch.drag = 0;
9692      }
9693    if (bd->client.illume.drag.fetch.locked)
9694      {
9695         bd->client.illume.drag.locked =
9696           ecore_x_e_illume_drag_locked_get(bd->client.win);
9697         bd->client.illume.drag.fetch.locked = 0;
9698      }
9699    if (bd->client.illume.win_state.fetch.state)
9700      {
9701         bd->client.illume.win_state.state =
9702            ecore_x_e_illume_window_state_get(bd->client.win);
9703         bd->client.illume.win_state.fetch.state = 0;
9704      }
9705    if (bd->changes.shape)
9706      {
9707         Ecore_X_Rectangle *rects;
9708         int num;
9709
9710         bd->changes.shape = 0;
9711         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
9712         if (rects)
9713           {
9714              int cw = 0, ch = 0;
9715
9716              /* This doesn't fix the race, but makes it smaller. we detect
9717               * this and if cw and ch != client w/h then mark this as needing
9718               * a shape change again to fixup next event loop.
9719               */
9720              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9721              if ((cw != bd->client.w) || (ch != bd->client.h))
9722                bd->changes.shape = 1;
9723              if ((num == 1) &&
9724                  (rects[0].x == 0) &&
9725                  (rects[0].y == 0) &&
9726                  ((int)rects[0].width == cw) &&
9727                  ((int)rects[0].height == ch))
9728                {
9729                   if (bd->client.shaped)
9730                     {
9731                        bd->client.shaped = 0;
9732                        if (!bd->bordername)
9733                          bd->client.border.changed = 1;
9734                     }
9735                }
9736              else
9737                {
9738                   if (!bd->client.shaped)
9739                     {
9740                        bd->client.shaped = 1;
9741                        if (!bd->bordername)
9742                          bd->client.border.changed = 1;
9743                     }
9744                }
9745              free(rects);
9746           }
9747         else
9748           {
9749              // FIXME: no rects i think can mean... totally empty window
9750              bd->client.shaped = 0;
9751              if (!bd->bordername)
9752                bd->client.border.changed = 1;
9753           }
9754         bd->need_shape_merge = 1;
9755      }
9756    if (bd->changes.shape_input)
9757      {
9758         Ecore_X_Rectangle *rects;
9759         int num;
9760
9761         bd->changes.shape_input = 0;
9762         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
9763         if (rects)
9764           {
9765              int cw = 0, ch = 0;
9766
9767              /* This doesn't fix the race, but makes it smaller. we detect
9768               * this and if cw and ch != client w/h then mark this as needing
9769               * a shape change again to fixup next event loop.
9770               */
9771              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9772              if ((cw != bd->client.w) || (ch != bd->client.h))
9773                bd->changes.shape_input = 1;
9774              if ((num == 1) &&
9775                  (rects[0].x == 0) &&
9776                  (rects[0].y == 0) &&
9777                  ((int)rects[0].width == cw) &&
9778                  ((int)rects[0].height == ch))
9779                {
9780                   if (bd->shaped_input)
9781                     {
9782                        bd->shaped_input = 0;
9783                        if (!bd->bordername)
9784                          bd->client.border.changed = 1;
9785                     }
9786                }
9787              else
9788                {
9789                   if (!bd->shaped_input)
9790                     {
9791                        bd->shaped_input = 1;
9792                        if (!bd->bordername)
9793                          bd->client.border.changed = 1;
9794                     }
9795                }
9796              free(rects);
9797           }
9798         else
9799           {
9800              bd->shaped_input = 1;
9801              if (!bd->bordername)
9802                bd->client.border.changed = 1;
9803           }
9804         bd->need_shape_merge = 1;
9805      }
9806    if (bd->client.mwm.fetch.hints)
9807      {
9808         int pb;
9809
9810         bd->client.mwm.exists =
9811           ecore_x_mwm_hints_get(bd->client.win,
9812                                 &bd->client.mwm.func,
9813                                 &bd->client.mwm.decor,
9814                                 &bd->client.mwm.input);
9815         pb = bd->client.mwm.borderless;
9816         bd->client.mwm.borderless = 0;
9817         if (bd->client.mwm.exists)
9818           {
9819              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
9820                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
9821                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
9822                bd->client.mwm.borderless = 1;
9823           }
9824         if (bd->client.mwm.borderless != pb)
9825           {
9826              if ((!bd->lock_border) || (!bd->client.border.name))
9827                bd->client.border.changed = 1;
9828           }
9829         bd->client.mwm.fetch.hints = 0;
9830         rem_change = 1;
9831      }
9832    if (bd->client.e.fetch.video_parent)
9833      {
9834         /* unlinking child/parent */
9835         if (bd->client.e.state.video_parent_border != NULL)
9836           {
9837              bd->client.e.state.video_parent_border->client.e.state.video_child =
9838                eina_list_remove
9839                (bd->client.e.state.video_parent_border->client.e.state.video_child,
9840                    bd);
9841           }
9842
9843         ecore_x_window_prop_card32_get(bd->client.win,
9844                                        ECORE_X_ATOM_E_VIDEO_PARENT,
9845                                        &bd->client.e.state.video_parent,
9846                                        1);
9847
9848         /* linking child/parent */
9849         if (bd->client.e.state.video_parent != 0)
9850           {
9851              E_Border *tmp;
9852              Eina_List *l;
9853
9854              EINA_LIST_FOREACH(borders, l, tmp)
9855                if (tmp->client.win == bd->client.e.state.video_parent)
9856                  {
9857                     /* fprintf(stderr, "child added to parent \\o/\n"); */
9858                     bd->client.e.state.video_parent_border = tmp;
9859                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
9860                                                                        bd);
9861                     if (bd->desk != tmp->desk)
9862                       e_border_desk_set(bd, tmp->desk);
9863                     break;
9864                  }
9865           }
9866
9867         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
9868
9869         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
9870         rem_change = 1;
9871      }
9872    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
9873      {
9874         unsigned int xy[2];
9875
9876         ecore_x_window_prop_card32_get(bd->client.win,
9877                                        ECORE_X_ATOM_E_VIDEO_POSITION,
9878                                        xy,
9879                                        2);
9880         bd->client.e.state.video_position.x = xy[0];
9881         bd->client.e.state.video_position.y = xy[1];
9882         bd->client.e.state.video_position.updated = 1;
9883         bd->client.e.fetch.video_position = 0;
9884         bd->x = bd->client.e.state.video_position.x;
9885         bd->y = bd->client.e.state.video_position.y;
9886
9887         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
9888      }
9889    if (bd->client.netwm.update.state)
9890      {
9891         e_hints_window_state_set(bd);
9892         /* Some stats might change the border, like modal */
9893         if (((!bd->lock_border) || (!bd->client.border.name)) &&
9894             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
9895           {
9896              bd->client.border.changed = 1;
9897           }
9898         if (bd->parent)
9899           {
9900              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9901                {
9902                   bd->parent->modal = bd;
9903                   if (bd->parent->focused)
9904                     e_border_focus_set(bd, 1, 1);
9905                }
9906           }
9907         else if (bd->leader)
9908           {
9909              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9910                {
9911                   bd->leader->modal = bd;
9912                   if (bd->leader->focused)
9913                     e_border_focus_set(bd, 1, 1);
9914                   else
9915                     {
9916                        Eina_List *l;
9917                        E_Border *child;
9918
9919                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9920                          {
9921                             if ((child != bd) && (child->focused))
9922                               e_border_focus_set(bd, 1, 1);
9923                          }
9924                     }
9925                }
9926           }
9927         bd->client.netwm.update.state = 0;
9928      }
9929
9930    if (bd->new_client)
9931      {
9932         E_Event_Border_Add *ev;
9933         E_Exec_Instance *inst;
9934
9935         ev = E_NEW(E_Event_Border_Add, 1);
9936         ev->border = bd;
9937         e_object_ref(E_OBJECT(bd));
9938         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
9939         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
9940
9941         if ((!bd->lock_border) || (!bd->client.border.name))
9942           bd->client.border.changed = 1;
9943
9944           {
9945              char *str = NULL;
9946
9947              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
9948                  ((bd->client.icccm.client_leader > 0) &&
9949                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
9950                 )
9951                {
9952                   if (!strncmp(str, "E_START|", 8))
9953                     {
9954                        int id;
9955
9956                        id = atoi(str + 8);
9957                        if (id > 0) bd->client.netwm.startup_id = id;
9958                     }
9959                   free(str);
9960                }
9961           }
9962         /* It's ok not to have fetch flag, should only be set on startup
9963          *     * and not changed. */
9964         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
9965           {
9966              if (bd->client.icccm.client_leader)
9967                {
9968                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
9969                     bd->client.netwm.pid = -1;
9970                }
9971              else
9972                bd->client.netwm.pid = -1;
9973           }
9974
9975         if (!bd->re_manage)
9976           {
9977              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
9978                                                         bd->client.netwm.pid);
9979              if ((inst) && (inst->used == 0))
9980                {
9981                   E_Zone *zone;
9982                   E_Desk *desk;
9983
9984                   inst->used++;
9985                   zone = e_container_zone_number_get(bd->zone->container,
9986                                                      inst->screen);
9987                   if (zone) e_border_zone_set(bd, zone);
9988                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
9989                                           inst->desk_y);
9990                   if (desk) e_border_desk_set(bd, desk);
9991                   e_exec_instance_found(inst);
9992                }
9993
9994              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
9995                {
9996                   E_Border *bdl = NULL;
9997
9998                   bdl = bd->parent;
9999                   if (!bdl)
10000                     {
10001                        if (bd->leader) bdl = bd->leader;
10002                     }
10003                   if (!bdl)
10004                     {
10005                        E_Border *child;
10006                        E_Border_List *bl;
10007
10008                        bl = e_container_border_list_first(bd->zone->container);
10009                        while ((child = e_container_border_list_next(bl)))
10010                          {
10011                             if (child == bd) continue;
10012                             if (e_object_is_del(E_OBJECT(child))) continue;
10013                             if ((bd->client.icccm.client_leader) &&
10014                                 (child->client.icccm.client_leader ==
10015                                     bd->client.icccm.client_leader))
10016                               {
10017                                  bdl = child;
10018                                  break;
10019                               }
10020                          }
10021                        e_container_border_list_free(bl);
10022                     }
10023                   if (bdl)
10024                     {
10025                        if (bdl->zone)
10026                          e_border_zone_set(bd, bdl->zone);
10027                        if (bdl->desk)
10028                          e_border_desk_set(bd, bdl->desk);
10029                        else
10030                          e_border_stick(bd);
10031                     }
10032                }
10033           }
10034      }
10035
10036 #ifdef _F_USE_DESK_WINDOW_PROFILE_
10037    if (need_desk_set)
10038      {
10039         E_Container *con = bd->zone->container;
10040         E_Desk *desk = NULL;
10041         Eina_List *l;
10042         const char *str;
10043         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
10044           {
10045              desk = e_container_desk_window_profile_get(con, str);
10046              if (desk)
10047                {
10048                   if (bd->desk != desk)
10049                     {
10050                        bd->client.e.state.profile = eina_stringshare_add(str);
10051                        if (bd->zone != desk->zone)
10052                          e_border_zone_set(bd, desk->zone);
10053                        e_border_desk_set(bd, desk);
10054                     }
10055                   break;
10056                }
10057           }
10058      }
10059 #endif
10060 #ifdef _F_ZONE_WINDOW_ROTATION_
10061    if ((e_config->wm_win_rotation) &&
10062        (need_rotation_set))
10063      {
10064         ELB(ELBT_ROT, "NEED ROT", bd->client.win);
10065         Eina_Bool _rot = _e_border_rotation_check(bd);
10066         /* check whether rotation is available for sub borders such as prediction and magnifier */
10067         if (_rot)
10068           {
10069              Eina_List *ll;
10070              E_Border *_child;
10071              Eina_List *_list = _e_border_sub_borders_new(bd);
10072              EINA_LIST_FOREACH(_list, ll, _child)
10073                {
10074                   if ((_child->client.e.state.rot.support) ||
10075                       (_child->client.e.state.rot.app_set))
10076                     _e_border_rotation_check(_child);
10077                }
10078              eina_list_free(_list);
10079           }
10080      }
10081 #endif
10082
10083    /* PRE_POST_FETCH calls e_remember apply for new client */
10084    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
10085    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
10086    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
10087
10088    if (bd->need_reparent)
10089      {
10090         if (!bd->internal)
10091           ecore_x_window_save_set_add(bd->client.win);
10092         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
10093         if (bd->visible)
10094           {
10095              if ((bd->new_client) && (bd->internal) &&
10096                  (bd->internal_ecore_evas))
10097                ecore_evas_show(bd->internal_ecore_evas);
10098              ecore_x_window_show(bd->client.win);
10099           }
10100         bd->need_reparent = 0;
10101      }
10102
10103    if ((bd->client.border.changed) && (!bd->shaded) &&
10104        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10105      {
10106         const char *bordername;
10107
10108         if (bd->fullscreen)
10109           bordername = "borderless";
10110         else if (bd->bordername)
10111           bordername = bd->bordername;
10112         else if ((bd->client.mwm.borderless) || (bd->borderless))
10113           bordername = "borderless";
10114         else if (((bd->client.icccm.transient_for != 0) ||
10115                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
10116                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10117                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10118           bordername = "noresize_dialog";
10119         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10120                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10121           bordername = "noresize";
10122         else if (bd->client.shaped)
10123           bordername = "shaped";
10124         else if ((!bd->client.icccm.accepts_focus) &&
10125                  (!bd->client.icccm.take_focus))
10126           bordername = "nofocus";
10127         else if (bd->client.icccm.urgent)
10128           bordername = "urgent";
10129         else if ((bd->client.icccm.transient_for != 0) ||
10130                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10131           bordername = "dialog";
10132         else if (bd->client.netwm.state.modal)
10133           bordername = "modal";
10134         else if ((bd->client.netwm.state.skip_taskbar) ||
10135                  (bd->client.netwm.state.skip_pager))
10136           bordername = "skipped";
10137         else if ((bd->internal) && (bd->client.icccm.class) &&
10138                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
10139           bordername = "internal_fileman";
10140         else
10141           bordername = e_config->theme_default_border_style;
10142         if (!bordername) bordername = "default";
10143
10144         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
10145           {
10146              Evas_Object *o;
10147              char buf[4096];
10148              int ok;
10149
10150              bd->changes.border = 1;
10151              eina_stringshare_replace(&bd->client.border.name, bordername);
10152
10153              if (bd->bg_object)
10154                {
10155                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
10156                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
10157                   bd->changes.size = 1;
10158                   evas_object_del(bd->bg_object);
10159                }
10160              o = edje_object_add(bd->bg_evas);
10161              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
10162              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10163              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
10164                {
10165                   if (bd->client.border.name != e_config->theme_default_border_style)
10166                     {
10167                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
10168                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10169                     }
10170                   if (!ok)
10171                     {
10172                        ok = e_theme_edje_object_set(o, "base/theme/borders",
10173                                                     "e/widgets/border/default/border");
10174                        if (ok)
10175                          {
10176                             /* Reset default border style to default */
10177                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
10178                             e_config_save_queue();
10179                          }
10180                     }
10181                }
10182
10183              bd->shaped = 0;
10184              if (ok)
10185                {
10186                   const char *shape_option, *argb_option;
10187                   int use_argb = 0;
10188
10189                   bd->bg_object = o;
10190
10191                   if ((e_config->use_composite) && (!bd->client.argb))
10192                     {
10193                        argb_option = edje_object_data_get(o, "argb");
10194                        if ((argb_option) && (!strcmp(argb_option, "1")))
10195                          use_argb = 1;
10196
10197                        if (use_argb != bd->argb)
10198                          _e_border_frame_replace(bd, use_argb);
10199
10200                        o = bd->bg_object;
10201                     }
10202
10203                   if (!bd->argb)
10204                     {
10205                        shape_option = edje_object_data_get(o, "shaped");
10206                        if ((shape_option) && (!strcmp(shape_option, "1")))
10207                          bd->shaped = 1;
10208                     }
10209
10210                   if (bd->client.netwm.name)
10211                     edje_object_part_text_set(o, "e.text.title",
10212                                               bd->client.netwm.name);
10213                   else if (bd->client.icccm.title)
10214                     edje_object_part_text_set(o, "e.text.title",
10215                                               bd->client.icccm.title);
10216                }
10217              else
10218                {
10219                   evas_object_del(o);
10220                   bd->bg_object = NULL;
10221                }
10222
10223              _e_border_client_inset_calc(bd);
10224
10225              bd->w += (bd->client_inset.l + bd->client_inset.r);
10226              bd->h += (bd->client_inset.t + bd->client_inset.b);
10227              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
10228              bd->changes.size = 1;
10229              /*  really needed ? */
10230              ecore_x_window_move(bd->client.shell_win,
10231                                  bd->client_inset.l,
10232                                  bd->client_inset.t);
10233
10234              if (bd->maximized != E_MAXIMIZE_NONE)
10235                {
10236                   E_Maximize maximized = bd->maximized;
10237
10238                   /* to force possible resizes */
10239                   bd->maximized = E_MAXIMIZE_NONE;
10240
10241                   _e_border_maximize(bd, maximized);
10242
10243                   /* restore maximized state */
10244                   bd->maximized = maximized;
10245
10246                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
10247                                                bd->maximized & E_MAXIMIZE_VERTICAL);
10248                }
10249              if (bd->bg_object)
10250                {
10251                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
10252                                                   _e_border_cb_signal_bind, bd);
10253                   if (bd->focused)
10254                     {
10255                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
10256                        if (bd->icon_object)
10257                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10258                     }
10259                   if (bd->shaded)
10260                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
10261                   if (bd->sticky)
10262                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
10263                   if (bd->hung)
10264                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
10265                   // FIXME: in eval -do differently
10266                   //         edje_object_message_signal_process(bd->bg_object);
10267                   //         e_border_frame_recalc(bd);
10268
10269                   evas_object_move(bd->bg_object, 0, 0);
10270                   evas_object_resize(bd->bg_object, bd->w, bd->h);
10271                   evas_object_show(bd->bg_object);
10272                }
10273           }
10274         bd->client.border.changed = 0;
10275
10276         if (bd->icon_object)
10277           {
10278              if (bd->bg_object)
10279                {
10280                   evas_object_show(bd->icon_object);
10281                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10282                }
10283              else
10284                evas_object_hide(bd->icon_object);
10285           }
10286      }
10287
10288    if (rem_change) e_remember_update(bd);
10289
10290    if (change_urgent)
10291      {
10292         E_Event_Border_Urgent_Change *ev;
10293
10294         if (bd->client.icccm.urgent)
10295           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
10296         else
10297           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
10298
10299         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
10300         ev->border = bd;
10301         e_object_ref(E_OBJECT(bd));
10302         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
10303                         _e_border_event_border_urgent_change_free, NULL);
10304      }
10305
10306    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10307 }
10308
10309 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10310 static void
10311 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10312 {
10313    E_Border* temp_bd = NULL;
10314    E_Border* top_focusable_bd = NULL;
10315    Eina_Bool is_fully_obscured = EINA_FALSE;
10316    Ecore_X_XRegion *visible_region = NULL;
10317    Ecore_X_XRegion *win_region = NULL;
10318    Ecore_X_Rectangle visible_rect, win_rect;
10319    E_Border_List *bl;
10320
10321    // set the entire visible region as a root geometry
10322    visible_rect.x = bd->zone->x;
10323    visible_rect.y = bd->zone->y;
10324    visible_rect.width = bd->zone->w;
10325    visible_rect.height = bd->zone->h;
10326
10327    visible_region = ecore_x_xregion_new();
10328    if (!visible_region) return;
10329
10330    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10331
10332    bl = e_container_border_list_last(bd->zone->container);
10333    while ((temp_bd = e_container_border_list_prev(bl)))
10334      {
10335         if (temp_bd == bd) break;
10336
10337         if (temp_bd == focused) continue;
10338         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10339         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10340         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10341             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10342             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10343             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10344             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10345             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10346             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10347           {
10348              if (!top_focusable_bd)
10349                {
10350                   top_focusable_bd = temp_bd;
10351                }
10352
10353              win_rect.x = temp_bd->x;
10354              win_rect.y = temp_bd->y;
10355              win_rect.width = temp_bd->w;
10356              win_rect.height = temp_bd->h;
10357
10358              // if it stick out or is bigger than the entire visible region,
10359              // clip it by the entire visible's geometry.
10360              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10361                                   win_rect.width, win_rect.height,
10362                                   visible_rect.x, visible_rect.y,
10363                                   (int)(visible_rect.width), (int)(visible_rect.height));
10364
10365              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10366                {
10367                   win_region = ecore_x_xregion_new();
10368                   if (win_region)
10369                     {
10370                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10371                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10372                        ecore_x_xregion_free(win_region);
10373                        win_region = NULL;
10374
10375                        if (ecore_x_xregion_is_empty(visible_region))
10376                          {
10377                             is_fully_obscured = EINA_TRUE;
10378                             break;
10379                          }
10380                     }
10381                }
10382           }
10383      }
10384
10385    if (is_fully_obscured == EINA_TRUE)
10386      {
10387         e_border_focus_set(top_focusable_bd, 1, 1);
10388      }
10389    else
10390      {
10391         e_border_focus_set(bd, 1, 1);
10392      }
10393
10394    if (visible_region) ecore_x_xregion_free(visible_region);
10395    e_container_border_list_free(bl);
10396 }
10397
10398 static void
10399 _e_border_latest_stacked_focus(E_Border *bd)
10400 {
10401    E_Border *temp_bd;
10402    int root_w, root_h;
10403
10404    root_w = bd->zone->w;
10405    root_h = bd->zone->h;
10406
10407    Eina_List *l;
10408    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10409      {
10410         if (bd == temp_bd) continue;
10411         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10412         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10413
10414         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10415             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10416             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10417             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10418             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10419             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10420             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10421           {
10422              _e_border_latest_stacked_focus_check_set(temp_bd);
10423              break;
10424           }
10425      }
10426 }
10427
10428 static void
10429 _e_border_check_stack (E_Border *bd)
10430 {
10431    E_Border* temp_bd = NULL;
10432    E_Border* top_bd = NULL;
10433    int passed_focus = 0;
10434    int passed = 0;
10435    int root_w = bd->zone->w;
10436    int root_h = bd->zone->h;
10437
10438    E_Border_List *bl;
10439    bl = e_container_border_list_last(bd->zone->container);
10440    while ((temp_bd = e_container_border_list_prev(bl)))
10441      {
10442         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10443         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10444         if ((temp_bd != bd) &&
10445             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10446
10447         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10448            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10449            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10450            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10451            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10452            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10453            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10454           {
10455              if (bd == temp_bd)
10456                {
10457                   if (!passed)
10458                     {
10459                        e_border_focus_set_with_pointer(bd);
10460                        break;
10461                     }
10462                   else
10463                     {
10464                        if (!passed_focus)
10465                          {
10466                             e_border_focus_set_with_pointer(top_bd);
10467                          }
10468                        break;
10469                     }
10470                }
10471              else
10472                {
10473                   if (!passed)
10474                     {
10475                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10476                          {
10477                             if (!bd->lock_focus_out)
10478                               {
10479                                  e_border_focus_latest_set(bd);
10480                               }
10481                          }
10482                     }
10483                }
10484
10485              if (!passed)
10486                {
10487                   passed = 1;
10488                   top_bd = temp_bd;
10489                }
10490
10491              if (temp_bd == focused)
10492                {
10493                   passed_focus = 1;
10494                }
10495           }
10496      }
10497    e_container_border_list_free(bl);
10498 }
10499
10500 static void
10501 _e_border_focus_top_stack_set(E_Border* bd)
10502 {
10503    E_Border *temp_bd;
10504    int root_w, root_h;
10505
10506    root_w = bd->zone->w;
10507    root_h = bd->zone->h;
10508
10509    E_Border_List *bl;
10510    bl = e_container_border_list_last(bd->zone->container);
10511    while ((temp_bd = e_container_border_list_prev(bl)))
10512      {
10513         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10514         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10515         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
10516
10517         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10518            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10519            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10520            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10521            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10522            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10523            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10524           {
10525              if (!temp_bd->focused)
10526                {
10527                   /* this border is the top of the latest stack */
10528                   e_border_focus_set (temp_bd, 1, 1);
10529                }
10530              break;
10531           }
10532      }
10533    e_container_border_list_free(bl);
10534 }
10535 #endif
10536
10537 static void
10538 _e_border_eval(E_Border *bd)
10539 {
10540    E_Event_Border_Property *event;
10541    E_Border_Pending_Move_Resize *pnd;
10542    int rem_change = 0;
10543    int send_event = 1;
10544
10545    if (e_object_is_del(E_OBJECT(bd)))
10546      {
10547         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
10548         bd->changed = 0;
10549         return;
10550      }
10551
10552    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
10553
10554    if (bd->new_client)
10555      {
10556         int zx = 0, zy = 0, zw = 0, zh = 0;
10557
10558         if (bd->zone)
10559           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
10560
10561         /*
10562          * Limit maximum size of windows to useful geometry
10563          */
10564         // TODO: temoporary limited maximize algorithm
10565         // ->
10566         /*if (bd->w > zw)
10567           rw = zw;
10568           else
10569           rw = bd->w;
10570
10571           if (bd->h > zh)
10572           rh = zh;
10573           else
10574           rh = bd->h;
10575
10576           if ((rw != bd->w) || (rh != bd->h))
10577           {
10578           bd->w = rw;
10579           bd->h = rh;
10580           e_border_resize (bd, bd->w, bd->h);
10581           }*/
10582         // <-
10583
10584         if (bd->re_manage)
10585           {
10586              bd->x -= bd->client_inset.l;
10587              bd->y -= bd->client_inset.t;
10588              bd->changes.pos = 1;
10589              bd->placed = 1;
10590           }
10591         else if ((!bd->placed) && (bd->client.icccm.request_pos))
10592           {
10593
10594              Ecore_X_Window_Attributes *att;
10595              int bw;
10596
10597              att = &bd->client.initial_attributes;
10598              bw = att->border * 2;
10599              switch (bd->client.icccm.gravity)
10600                {
10601                 case ECORE_X_GRAVITY_N:
10602                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10603                    bd->y = att->y;
10604                    break;
10605
10606                 case ECORE_X_GRAVITY_NE:
10607                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10608                    bd->y = att->y;
10609                    break;
10610
10611                 case ECORE_X_GRAVITY_E:
10612                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10613                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10614                    break;
10615
10616                 case ECORE_X_GRAVITY_SE:
10617                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10618                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10619                    break;
10620
10621                 case ECORE_X_GRAVITY_S:
10622                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10623                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10624                    break;
10625
10626                 case ECORE_X_GRAVITY_SW:
10627                    bd->x = att->x;
10628                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10629                    break;
10630
10631                 case ECORE_X_GRAVITY_W:
10632                    bd->x = att->x;
10633                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10634                    break;
10635
10636                 case ECORE_X_GRAVITY_CENTER:
10637                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10638                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10639                    break;
10640
10641                 case ECORE_X_GRAVITY_NW:
10642                 default:
10643                    bd->x = att->x;
10644                    bd->y = att->y;
10645                }
10646
10647              /*
10648               * This ensures that windows that like to open with a x/y
10649               * position smaller than returned by e_zone_useful_geometry_get()
10650               * are moved to useful positions.
10651               */
10652              // ->
10653              if (e_config->geometry_auto_move)
10654                {
10655                   if (bd->x < zx)
10656                     bd->x = zx;
10657
10658                   if (bd->y < zy)
10659                     bd->y = zy;
10660
10661                   if (bd->x + bd->w > zx + zw)
10662                     bd->x = zx + zw - bd->w;
10663
10664                   if (bd->y + bd->h > zy + zh)
10665                     bd->y = zy + zh - bd->h;
10666                   // <--
10667
10668                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
10669                     {
10670                        bd->changes.pos = 1;
10671                        bd->placed = 1;
10672                     }
10673                }
10674              else
10675                {
10676                   bd->changes.pos = 1;
10677                   bd->placed = 1;
10678                }
10679           }
10680         if (!bd->placed)
10681           {
10682              /* FIXME: special placement for dialogs etc. etc. etc goes
10683               * here */
10684              /* FIXME: what if parent is not on this desktop - or zone? */
10685              if ((bd->parent) && (bd->parent->visible))
10686                {
10687                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
10688                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
10689                   bd->changes.pos = 1;
10690                   bd->placed = 1;
10691                }
10692 #if 0
10693              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10694                {
10695                   /* TODO: Place in center of group */
10696                }
10697 #endif
10698              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
10699                {
10700                   bd->x = zx + ((zw - bd->w) / 2);
10701                   bd->y = zy + ((zh - bd->h) / 2);
10702                   bd->changes.pos = 1;
10703                   bd->placed = 1;
10704                }
10705           }
10706         if (!bd->placed)
10707           {
10708              Eina_List *skiplist = NULL;
10709              int new_x, new_y;
10710
10711              if (zw > bd->w)
10712                new_x = zx + (rand() % (zw - bd->w));
10713              else
10714                new_x = zx;
10715              if (zh > bd->h)
10716                new_y = zy + (rand() % (zh - bd->h));
10717              else
10718                new_y = zy;
10719
10720              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
10721                {
10722                   skiplist = eina_list_append(skiplist, bd);
10723                   if (bd->desk)
10724                     e_place_desk_region_smart(bd->desk, skiplist,
10725                                               bd->x, bd->y, bd->w, bd->h,
10726                                               &new_x, &new_y);
10727                   else
10728                     e_place_zone_region_smart(bd->zone, skiplist,
10729                                               bd->x, bd->y, bd->w, bd->h,
10730                                               &new_x, &new_y);
10731                   eina_list_free(skiplist);
10732                }
10733              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
10734                {
10735                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
10736                                       &new_x, &new_y);
10737                }
10738              else
10739                {
10740                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
10741                                       bd->client_inset.t, &new_x, &new_y);
10742                }
10743              bd->x = new_x;
10744              bd->y = new_y;
10745              bd->changes.pos = 1;
10746           }
10747
10748         EINA_LIST_FREE(bd->pending_move_resize, pnd)
10749           {
10750              if ((!bd->lock_client_location) && (pnd->move))
10751                {
10752                   bd->x = pnd->x;
10753                   bd->y = pnd->y;
10754                   bd->changes.pos = 1;
10755                   bd->placed = 1;
10756                   if (pnd->without_border)
10757                     {
10758                        bd->x -= bd->client_inset.l;
10759                        bd->y -= bd->client_inset.t;
10760                     }
10761                }
10762              if ((!bd->lock_client_size) && (pnd->resize))
10763                {
10764                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
10765                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
10766                   bd->client.w = pnd->w;
10767                   bd->client.h = pnd->h;
10768                   bd->changes.size = 1;
10769                }
10770
10771              free(pnd);
10772           }
10773
10774         /* Recreate state */
10775         e_hints_window_init(bd);
10776         if ((bd->client.e.state.centered) &&
10777             ((!bd->remember) ||
10778              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
10779           {
10780              bd->x = zx + (zw - bd->w) / 2;
10781              bd->y = zy + (zh - bd->h) / 2;
10782              bd->changes.pos = 1;
10783              bd->placed = 1;
10784           }
10785
10786         _e_border_client_move_resize_send(bd);
10787
10788         /* if the explicit geometry request asks for the app to be
10789          * in another zone - well move it there */
10790         {
10791            E_Zone *zone;
10792
10793            zone = e_container_zone_at_point_get(bd->zone->container,
10794                                                 bd->x + (bd->w / 2),
10795                                                 bd->y + (bd->h / 2));
10796            if (!zone)
10797              zone = e_container_zone_at_point_get(bd->zone->container,
10798                                                   bd->x,
10799                                                   bd->y);
10800            if (!zone)
10801              zone = e_container_zone_at_point_get(bd->zone->container,
10802                                                   bd->x + bd->w - 1,
10803                                                   bd->y);
10804            if (!zone)
10805              zone = e_container_zone_at_point_get(bd->zone->container,
10806                                                   bd->x + bd->w - 1,
10807                                                   bd->y + bd->h - 1);
10808            if (!zone)
10809              zone = e_container_zone_at_point_get(bd->zone->container,
10810                                                   bd->x,
10811                                                   bd->y + bd->h - 1);
10812            if ((zone) && (zone != bd->zone))
10813              e_border_zone_set(bd, zone);
10814         }
10815      }
10816
10817    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
10818
10819    /* effect changes to the window border itself */
10820    if ((bd->changes.shading))
10821      {
10822         /*  show at start of unshade (but don't hide until end of shade) */
10823         if (bd->shaded)
10824           ecore_x_window_raise(bd->client.shell_win);
10825         bd->changes.shading = 0;
10826         rem_change = 1;
10827      }
10828    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
10829      {
10830         if (bd->shaded)
10831           ecore_x_window_lower(bd->client.shell_win);
10832         else
10833           ecore_x_window_raise(bd->client.shell_win);
10834         bd->changes.shaded = 0;
10835         rem_change = 1;
10836      }
10837    else if ((bd->changes.shaded) && (bd->changes.pos))
10838      {
10839         if (bd->shaded)
10840           ecore_x_window_lower(bd->client.shell_win);
10841         else
10842           ecore_x_window_raise(bd->client.shell_win);
10843         bd->changes.size = 1;
10844         bd->changes.shaded = 0;
10845         rem_change = 1;
10846      }
10847    else if ((bd->changes.shaded) && (bd->changes.size))
10848      {
10849         if (bd->shaded)
10850           ecore_x_window_lower(bd->client.shell_win);
10851         else
10852           ecore_x_window_raise(bd->client.shell_win);
10853         bd->changes.shaded = 0;
10854         rem_change = 1;
10855      }
10856    else if (bd->changes.shaded)
10857      {
10858         if (bd->shaded)
10859           ecore_x_window_lower(bd->client.shell_win);
10860         else
10861           ecore_x_window_raise(bd->client.shell_win);
10862         bd->changes.size = 1;
10863         bd->changes.shaded = 0;
10864         rem_change = 1;
10865      }
10866
10867    if (bd->changes.size)
10868      {
10869         int x = 0, y = 0, xx = 0, yy = 0;
10870
10871         if ((bd->shaded) && (!bd->shading))
10872           {
10873              evas_obscured_clear(bd->bg_evas);
10874           }
10875         else
10876           {
10877              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
10878              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
10879
10880              evas_obscured_clear(bd->bg_evas);
10881              evas_obscured_rectangle_add(bd->bg_evas,
10882                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
10883
10884              if (bd->shading)
10885                {
10886                   if (bd->shade.dir == E_DIRECTION_UP)
10887                     {
10888                        y = yy - bd->client.h;
10889                     }
10890                   else if (bd->shade.dir == E_DIRECTION_LEFT)
10891                     {
10892                        x = xx - bd->client.w;
10893                     }
10894                }
10895           }
10896
10897         if (bd->client.e.state.video)
10898           {
10899              if (bd->client.e.state.video_position.updated)
10900                {
10901                   ecore_x_window_move(bd->win,
10902                                       bd->client.e.state.video_parent_border->x +
10903                                       bd->client.e.state.video_parent_border->client_inset.l +
10904                                       bd->client.e.state.video_parent_border->fx.x +
10905                                       bd->client.e.state.video_position.x,
10906                                       bd->client.e.state.video_parent_border->y +
10907                                       bd->client.e.state.video_parent_border->client_inset.t +
10908                                       bd->client.e.state.video_parent_border->fx.y +
10909                                       bd->client.e.state.video_position.y);
10910                   bd->client.e.state.video_position.updated = 0;
10911                }
10912           }
10913         else if (!bd->changes.pos)
10914           {
10915              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
10916              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
10917              bd->post_resize = 1;
10918           }
10919         else
10920           {
10921              E_Border *tmp;
10922              Eina_List *l;
10923
10924              ecore_x_window_move_resize(bd->win,
10925                                         bd->x + bd->fx.x,
10926                                         bd->y + bd->fx.y,
10927                                         bd->w, bd->h);
10928
10929              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
10930                ecore_x_window_move(tmp->win,
10931                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
10932                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
10933           }
10934
10935         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
10936
10937         if ((!bd->shaded) || (bd->shading))
10938           ecore_x_window_move_resize(bd->client.shell_win,
10939                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
10940
10941         if (bd->internal_ecore_evas)
10942           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
10943         else if (!bd->client.e.state.video)
10944           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
10945
10946         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
10947         evas_object_resize(bd->bg_object, bd->w, bd->h);
10948         e_container_shape_resize(bd->shape, bd->w, bd->h);
10949         if (bd->changes.pos)
10950           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
10951
10952         _e_border_client_move_resize_send(bd);
10953
10954         bd->changes.pos = 0;
10955         bd->changes.size = 0;
10956         rem_change = 1;
10957      }
10958    else if (bd->changes.pos)
10959      {
10960         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
10961         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
10962         bd->post_move = 1;
10963
10964         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
10965
10966         _e_border_client_move_resize_send(bd);
10967
10968         bd->changes.pos = 0;
10969         rem_change = 1;
10970      }
10971
10972    if (bd->changes.reset_gravity)
10973      {
10974         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
10975         bd->changes.reset_gravity = 0;
10976         rem_change = 1;
10977      }
10978
10979    if (bd->need_shape_merge)
10980      {
10981         _e_border_shape_input_rectangle_set(bd);
10982         if ((bd->shaped) || (bd->client.shaped))
10983           {
10984              Ecore_X_Window twin, twin2;
10985              int x, y;
10986
10987              twin = ecore_x_window_override_new
10988                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
10989              if (bd->shaped)
10990                ecore_x_window_shape_window_set(twin, bd->bg_win);
10991              else
10992                {
10993                   Ecore_X_Rectangle rects[4];
10994
10995                   rects[0].x = 0;
10996                   rects[0].y = 0;
10997                   rects[0].width = bd->w;
10998                   rects[0].height = bd->client_inset.t;
10999                   rects[1].x = 0;
11000                   rects[1].y = bd->client_inset.t;
11001                   rects[1].width = bd->client_inset.l;
11002                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11003                   rects[2].x = bd->w - bd->client_inset.r;
11004                   rects[2].y = bd->client_inset.t;
11005                   rects[2].width = bd->client_inset.r;
11006                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11007                   rects[3].x = 0;
11008                   rects[3].y = bd->h - bd->client_inset.b;
11009                   rects[3].width = bd->w;
11010                   rects[3].height = bd->client_inset.b;
11011                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
11012                }
11013              twin2 = ecore_x_window_override_new
11014                (bd->zone->container->scratch_win, 0, 0,
11015                 bd->w - bd->client_inset.l - bd->client_inset.r,
11016                 bd->h - bd->client_inset.t - bd->client_inset.b);
11017              x = 0;
11018              y = 0;
11019              if ((bd->shading) || (bd->shaded))
11020                {
11021                   if (bd->shade.dir == E_DIRECTION_UP)
11022                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
11023                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11024                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
11025                }
11026              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
11027                                                 x, y);
11028              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
11029                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
11030                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
11031              ecore_x_window_shape_window_add_xy(twin, twin2,
11032                                                 bd->client_inset.l,
11033                                                 bd->client_inset.t);
11034              ecore_x_window_free(twin2);
11035              ecore_x_window_shape_window_set(bd->win, twin);
11036              ecore_x_window_free(twin);
11037           }
11038         else
11039           ecore_x_window_shape_mask_set(bd->win, 0);
11040         //      bd->need_shape_export = 1;
11041         bd->need_shape_merge = 0;
11042      }
11043
11044    if (bd->need_shape_export)
11045      {
11046         Ecore_X_Rectangle *rects, *orects;
11047         int num;
11048
11049         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
11050         if (rects)
11051           {
11052              int changed;
11053
11054              changed = 1;
11055              if ((num == bd->shape_rects_num) && (bd->shape_rects))
11056                {
11057                   int i;
11058
11059                   orects = bd->shape_rects;
11060                   changed = 0;
11061                   for (i = 0; i < num; i++)
11062                     {
11063                        if (rects[i].x < 0)
11064                          {
11065                             rects[i].width -= rects[i].x;
11066                             rects[i].x = 0;
11067                          }
11068                        if ((rects[i].x + (int)rects[i].width) > bd->w)
11069                          rects[i].width = rects[i].width - rects[i].x;
11070                        if (rects[i].y < 0)
11071                          {
11072                             rects[i].height -= rects[i].y;
11073                             rects[i].y = 0;
11074                          }
11075                        if ((rects[i].y + (int)rects[i].height) > bd->h)
11076                          rects[i].height = rects[i].height - rects[i].y;
11077
11078                        if ((orects[i].x != rects[i].x) ||
11079                            (orects[i].y != rects[i].y) ||
11080                            (orects[i].width != rects[i].width) ||
11081                            (orects[i].height != rects[i].height))
11082                          {
11083                             changed = 1;
11084                             break;
11085                          }
11086                     }
11087                }
11088              if (changed)
11089                {
11090                   if (bd->client.shaped)
11091                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
11092                   else
11093                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
11094                   E_FREE(bd->shape_rects);
11095                   bd->shape_rects = rects;
11096                   bd->shape_rects_num = num;
11097                   e_container_shape_rects_set(bd->shape, rects, num);
11098                }
11099              else
11100                free(rects);
11101           }
11102         else
11103           {
11104              E_FREE(bd->shape_rects);
11105              bd->shape_rects = NULL;
11106              bd->shape_rects_num = 0;
11107              e_container_shape_rects_set(bd->shape, NULL, 0);
11108           }
11109         bd->need_shape_export = 0;
11110      }
11111
11112    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
11113      {
11114         int x, y;
11115
11116         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
11117         if ((!bd->placed) && (!bd->re_manage) &&
11118             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
11119             (!((bd->client.icccm.transient_for != 0) ||
11120                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
11121             (!bdmove) && (!bdresize))
11122           {
11123              /* Set this window into moving state */
11124
11125              bd->cur_mouse_action = e_action_find("window_move");
11126              if (bd->cur_mouse_action)
11127                {
11128                   if ((!bd->cur_mouse_action->func.end_mouse) &&
11129                       (!bd->cur_mouse_action->func.end))
11130                     bd->cur_mouse_action = NULL;
11131                   if (bd->cur_mouse_action)
11132                     {
11133                        bd->x = x - (bd->w >> 1);
11134                        bd->y = y - (bd->client_inset.t >> 1);
11135                        bd->changed = 1;
11136                        bd->changes.pos = 1;
11137
11138                        _e_border_client_move_resize_send(bd);
11139                     }
11140                }
11141           }
11142
11143         _e_border_show(bd);
11144
11145         if (bd->cur_mouse_action)
11146           {
11147              bd->moveinfo.down.x = bd->x + bd->fx.x;
11148              bd->moveinfo.down.y = bd->y + bd->fx.y;
11149              bd->moveinfo.down.w = bd->w;
11150              bd->moveinfo.down.h = bd->h;
11151              bd->mouse.current.mx = x;
11152              bd->mouse.current.my = y;
11153              bd->moveinfo.down.button = 0;
11154              bd->moveinfo.down.mx = x;
11155              bd->moveinfo.down.my = y;
11156
11157              grabbed = 1;
11158              e_object_ref(E_OBJECT(bd->cur_mouse_action));
11159              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
11160              if (e_config->border_raise_on_mouse_action)
11161                e_border_raise(bd);
11162              e_border_focus_set(bd, 1, 1);
11163           }
11164         bd->changes.visible = 0;
11165         rem_change = 1;
11166      }
11167
11168    if (bd->changes.icon)
11169      {
11170         if (bd->desktop)
11171           {
11172              efreet_desktop_free(bd->desktop);
11173              bd->desktop = NULL;
11174           }
11175         if (bd->icon_object)
11176           {
11177              evas_object_del(bd->icon_object);
11178              bd->icon_object = NULL;
11179           }
11180         if (bd->remember && bd->remember->prop.desktop_file)
11181           {
11182              const char *desktop = bd->remember->prop.desktop_file;
11183
11184              bd->desktop = efreet_desktop_get(desktop);
11185              if (!bd->desktop)
11186                bd->desktop = efreet_util_desktop_name_find(desktop);
11187           }
11188         if (!bd->desktop)
11189           {
11190              if ((bd->client.icccm.name) && (bd->client.icccm.class))
11191                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
11192                                                                bd->client.icccm.class);
11193           }
11194         if (!bd->desktop)
11195           {
11196              /* libreoffice and maybe others match window class
11197                 with .desktop file name */
11198              if (bd->client.icccm.class)
11199                {
11200                   char buf[128];
11201                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
11202                   bd->desktop = efreet_util_desktop_file_id_find(buf);
11203                }
11204           }
11205         if (!bd->desktop)
11206           {
11207              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
11208                                                       bd->client.netwm.pid);
11209              if (bd->desktop) efreet_desktop_ref(bd->desktop);
11210           }
11211         if (!bd->desktop && bd->client.icccm.name)
11212           {
11213              /* this works for most cases as fallback. useful when app is
11214                 run from a shell  */
11215              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
11216           }
11217         if (!bd->desktop && bd->client.icccm.transient_for)
11218           {
11219              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
11220              if (bd2 && bd2->desktop)
11221                {
11222                   efreet_desktop_ref(bd2->desktop);
11223                   bd->desktop = bd2->desktop;
11224                }
11225           }
11226         if (bd->desktop)
11227           {
11228              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
11229                                             bd->desktop->orig_path);
11230           }
11231
11232         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
11233         if ((bd->focused) && (bd->icon_object))
11234           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
11235         if (bd->bg_object)
11236           {
11237              evas_object_show(bd->icon_object);
11238              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
11239           }
11240         else
11241           evas_object_hide(bd->icon_object);
11242
11243         {
11244            E_Event_Border_Icon_Change *ev;
11245
11246            ev = E_NEW(E_Event_Border_Icon_Change, 1);
11247            ev->border = bd;
11248            e_object_ref(E_OBJECT(bd));
11249            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
11250            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
11251                            _e_border_event_border_icon_change_free, NULL);
11252         }
11253         bd->changes.icon = 0;
11254      }
11255
11256    bd->new_client = 0;
11257    bd->changed = 0;
11258    bd->changes.stack = 0;
11259    bd->changes.prop = 0;
11260
11261    if ((bd->take_focus) || (bd->want_focus))
11262      {
11263         bd->take_focus = 0;
11264 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11265         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
11266             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
11267             (bd->want_focus))
11268 #else // original
11269         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
11270 #endif
11271           {
11272              bd->want_focus = 0;
11273 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11274              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
11275                 _e_border_check_stack(bd);
11276              else
11277 #endif
11278              e_border_focus_set_with_pointer(bd);
11279           }
11280         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11281           {
11282              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
11283                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
11284                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
11285                    e_border_focused_get())))
11286                {
11287                   e_border_focus_set_with_pointer(bd);
11288                }
11289           }
11290         else
11291           {
11292              /* focus window by default when it is the only one on desk */
11293              E_Border *bd2 = NULL;
11294              Eina_List *l;
11295              EINA_LIST_FOREACH(focus_stack, l, bd2)
11296                {
11297                   if (bd == bd2) continue;
11298                   if ((!bd2->iconic) && (bd2->visible) &&
11299                       ((bd->desk == bd2->desk) || bd2->sticky))
11300                     break;
11301                }
11302
11303              if (!bd2)
11304                {
11305                   e_border_focus_set_with_pointer(bd);
11306                }
11307           }
11308      }
11309
11310    if (bd->need_maximize)
11311      {
11312         E_Maximize max;
11313         max = bd->maximized;
11314         bd->maximized = E_MAXIMIZE_NONE;
11315         e_border_maximize(bd, max);
11316         bd->need_maximize = 0;
11317      }
11318
11319    if (bd->need_fullscreen)
11320      {
11321         e_border_fullscreen(bd, e_config->fullscreen_policy);
11322         bd->need_fullscreen = 0;
11323      }
11324
11325    if (rem_change)
11326      e_remember_update(bd);
11327
11328    if (send_event) // FIXME: send only if a property changed - above need to
11329      { // check on that. for now - always send.
11330         event = E_NEW(E_Event_Border_Property, 1);
11331         event->border = bd;
11332         e_object_ref(E_OBJECT(bd));
11333         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11334      }
11335    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11336 }
11337
11338 static void
11339 _e_border_moveinfo_gather(E_Border   *bd,
11340                           const char *source)
11341 {
11342    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11343    else if (e_util_glob_match(source, "mouse,*,2"))
11344      bd->moveinfo.down.button = 2;
11345    else if (e_util_glob_match(source, "mouse,*,3"))
11346      bd->moveinfo.down.button = 3;
11347    else bd->moveinfo.down.button = 0;
11348    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11349      {
11350         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11351         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11352      }
11353    else
11354      {
11355         bd->moveinfo.down.mx = bd->mouse.current.mx;
11356         bd->moveinfo.down.my = bd->mouse.current.my;
11357      }
11358 }
11359
11360 static void
11361 _e_border_resize_handle(E_Border *bd)
11362 {
11363    int x, y, w, h;
11364    int new_x, new_y, new_w, new_h;
11365    int tw, th;
11366    Eina_List *skiplist = NULL;
11367
11368    x = bd->x;
11369    y = bd->y;
11370    w = bd->w;
11371    h = bd->h;
11372
11373    if ((bd->resize_mode == RESIZE_TR) ||
11374        (bd->resize_mode == RESIZE_R) ||
11375        (bd->resize_mode == RESIZE_BR))
11376      {
11377         if ((bd->moveinfo.down.button >= 1) &&
11378             (bd->moveinfo.down.button <= 3))
11379           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11380             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11381         else
11382           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11383      }
11384    else if ((bd->resize_mode == RESIZE_TL) ||
11385             (bd->resize_mode == RESIZE_L) ||
11386             (bd->resize_mode == RESIZE_BL))
11387      {
11388         if ((bd->moveinfo.down.button >= 1) &&
11389             (bd->moveinfo.down.button <= 3))
11390           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11391             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11392         else
11393           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11394      }
11395
11396    if ((bd->resize_mode == RESIZE_TL) ||
11397        (bd->resize_mode == RESIZE_T) ||
11398        (bd->resize_mode == RESIZE_TR))
11399      {
11400         if ((bd->moveinfo.down.button >= 1) &&
11401             (bd->moveinfo.down.button <= 3))
11402           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11403             (bd->mouse.current.my - bd->moveinfo.down.my);
11404         else
11405           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11406      }
11407    else if ((bd->resize_mode == RESIZE_BL) ||
11408             (bd->resize_mode == RESIZE_B) ||
11409             (bd->resize_mode == RESIZE_BR))
11410      {
11411         if ((bd->moveinfo.down.button >= 1) &&
11412             (bd->moveinfo.down.button <= 3))
11413           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11414             (bd->mouse.current.my - bd->moveinfo.down.my);
11415         else
11416           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11417      }
11418
11419    tw = bd->w;
11420    th = bd->h;
11421
11422    if ((bd->resize_mode == RESIZE_TL) ||
11423        (bd->resize_mode == RESIZE_L) ||
11424        (bd->resize_mode == RESIZE_BL))
11425      x += (tw - w);
11426    if ((bd->resize_mode == RESIZE_TL) ||
11427        (bd->resize_mode == RESIZE_T) ||
11428        (bd->resize_mode == RESIZE_TR))
11429      y += (th - h);
11430
11431    skiplist = eina_list_append(skiplist, bd);
11432    e_resist_container_border_position(bd->zone->container, skiplist,
11433                                       bd->x, bd->y, bd->w, bd->h,
11434                                       x, y, w, h,
11435                                       &new_x, &new_y, &new_w, &new_h);
11436    eina_list_free(skiplist);
11437
11438    w = new_w;
11439    h = new_h;
11440    e_border_resize_limit(bd, &new_w, &new_h);
11441    if ((bd->resize_mode == RESIZE_TL) ||
11442        (bd->resize_mode == RESIZE_L) ||
11443        (bd->resize_mode == RESIZE_BL))
11444      new_x += (w - new_w);
11445    if ((bd->resize_mode == RESIZE_TL) ||
11446        (bd->resize_mode == RESIZE_T) ||
11447        (bd->resize_mode == RESIZE_TR))
11448      new_y += (h - new_h);
11449
11450    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11451 }
11452
11453 static Eina_Bool
11454 _e_border_shade_animator(void *data)
11455 {
11456    E_Border *bd = data;
11457    double dt, val;
11458    double dur = bd->client.h / e_config->border_shade_speed;
11459
11460    dt = ecore_loop_time_get() - bd->shade.start;
11461    val = dt / dur;
11462
11463    if (val < 0.0) val = 0.0;
11464    else if (val > 1.0) val = 1.0;
11465
11466    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11467      {
11468         bd->shade.val =
11469            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
11470         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11471      }
11472    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
11473      {
11474         bd->shade.val =
11475            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
11476         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11477      }
11478    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
11479      {
11480         bd->shade.val =
11481            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
11482         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11483      }
11484    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
11485      {
11486         bd->shade.val =
11487            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11488         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11489      }
11490    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
11491      {
11492         bd->shade.val =
11493            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
11494         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11495      }
11496    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
11497      {
11498         bd->shade.val =
11499            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
11500         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11501      }
11502    else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
11503      {
11504         bd->shade.val =
11505            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.0);
11506         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11507      }
11508    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE)
11509      {
11510         bd->shade.val =
11511            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
11512         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11513      }
11514    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
11515      {
11516         bd->shade.val =
11517            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
11518         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11519      }
11520    else
11521      {
11522         bd->shade.val =
11523            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11524         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11525      }
11526
11527    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
11528    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
11529    else if (bd->shade.val > .999)
11530      bd->shade.val = 1.0;
11531
11532    if (bd->shade.dir == E_DIRECTION_UP)
11533      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11534    else if (bd->shade.dir == E_DIRECTION_DOWN)
11535      {
11536         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11537         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
11538         bd->changes.pos = 1;
11539      }
11540    else if (bd->shade.dir == E_DIRECTION_LEFT)
11541      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11542    else if (bd->shade.dir == E_DIRECTION_RIGHT)
11543      {
11544         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11545         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
11546         bd->changes.pos = 1;
11547      }
11548
11549    if ((bd->shaped) || (bd->client.shaped))
11550      {
11551         bd->need_shape_merge = 1;
11552         bd->need_shape_export = 1;
11553      }
11554    if (bd->shaped_input)
11555      {
11556         bd->need_shape_merge = 1;
11557      }
11558    bd->changes.size = 1;
11559    bd->changed = 1;
11560
11561    /* we're done */
11562    if (val == 1)
11563      {
11564         E_Event_Border_Resize *ev;
11565
11566         bd->shading = 0;
11567         bd->shaded = !(bd->shaded);
11568         bd->changes.size = 1;
11569         bd->changes.shaded = 1;
11570         bd->changes.shading = 1;
11571         bd->changed = 1;
11572         bd->shade.anim = NULL;
11573
11574         if (bd->shaded)
11575           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
11576         else
11577           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
11578         edje_object_message_signal_process(bd->bg_object);
11579         e_border_frame_recalc(bd);
11580
11581         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
11582         ev = E_NEW(E_Event_Border_Resize, 1);
11583         ev->border = bd;
11584         e_object_ref(E_OBJECT(bd));
11585 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
11586         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
11587         return ECORE_CALLBACK_CANCEL;
11588      }
11589    return ECORE_CALLBACK_RENEW;
11590 }
11591
11592 static void
11593 _e_border_event_border_resize_free(void *data __UNUSED__,
11594                                    void      *ev)
11595 {
11596    E_Event_Border_Resize *e;
11597
11598    e = ev;
11599 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
11600    e_object_unref(E_OBJECT(e->border));
11601    E_FREE(e);
11602 }
11603
11604 static void
11605 _e_border_event_border_move_free(void *data __UNUSED__,
11606                                  void      *ev)
11607 {
11608    E_Event_Border_Move *e;
11609
11610    e = ev;
11611 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
11612    e_object_unref(E_OBJECT(e->border));
11613    E_FREE(e);
11614 }
11615
11616 static void
11617 _e_border_event_border_add_free(void *data __UNUSED__,
11618                                 void      *ev)
11619 {
11620    E_Event_Border_Add *e;
11621
11622    e = ev;
11623 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
11624    e_object_unref(E_OBJECT(e->border));
11625    E_FREE(e);
11626 }
11627
11628 static void
11629 _e_border_event_border_remove_free(void *data __UNUSED__,
11630                                    void      *ev)
11631 {
11632    E_Event_Border_Remove *e;
11633
11634    e = ev;
11635 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
11636    e_object_unref(E_OBJECT(e->border));
11637    E_FREE(e);
11638 }
11639
11640 static void
11641 _e_border_event_border_show_free(void *data __UNUSED__,
11642                                  void      *ev)
11643 {
11644    E_Event_Border_Show *e;
11645
11646    e = ev;
11647 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
11648    e_object_unref(E_OBJECT(e->border));
11649    E_FREE(e);
11650 }
11651
11652 static void
11653 _e_border_event_border_hide_free(void *data __UNUSED__,
11654                                  void      *ev)
11655 {
11656    E_Event_Border_Hide *e;
11657
11658    e = ev;
11659 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
11660    e_object_unref(E_OBJECT(e->border));
11661    E_FREE(e);
11662 }
11663
11664 static void
11665 _e_border_event_border_iconify_free(void *data __UNUSED__,
11666                                     void      *ev)
11667 {
11668    E_Event_Border_Iconify *e;
11669
11670    e = ev;
11671 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
11672    e_object_unref(E_OBJECT(e->border));
11673    E_FREE(e);
11674 }
11675
11676 static void
11677 _e_border_event_border_uniconify_free(void *data __UNUSED__,
11678                                       void      *ev)
11679 {
11680    E_Event_Border_Uniconify *e;
11681
11682    e = ev;
11683 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
11684    e_object_unref(E_OBJECT(e->border));
11685    E_FREE(e);
11686 }
11687
11688 static void
11689 _e_border_event_border_stick_free(void *data __UNUSED__,
11690                                   void      *ev)
11691 {
11692    E_Event_Border_Stick *e;
11693
11694    e = ev;
11695 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
11696    e_object_unref(E_OBJECT(e->border));
11697    E_FREE(e);
11698 }
11699
11700 static void
11701 _e_border_event_border_unstick_free(void *data __UNUSED__,
11702                                     void      *ev)
11703 {
11704    E_Event_Border_Unstick *e;
11705
11706    e = ev;
11707 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
11708    e_object_unref(E_OBJECT(e->border));
11709    E_FREE(e);
11710 }
11711
11712 static void
11713 _e_border_event_border_zone_set_free(void *data __UNUSED__,
11714                                      void      *ev)
11715 {
11716    E_Event_Border_Zone_Set *e;
11717
11718    e = ev;
11719 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
11720    e_object_unref(E_OBJECT(e->border));
11721    e_object_unref(E_OBJECT(e->zone));
11722    E_FREE(e);
11723 }
11724
11725 static void
11726 _e_border_event_border_desk_set_free(void *data __UNUSED__,
11727                                      void      *ev)
11728 {
11729    E_Event_Border_Desk_Set *e;
11730
11731    e = ev;
11732 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
11733    e_object_unref(E_OBJECT(e->border));
11734    e_object_unref(E_OBJECT(e->desk));
11735    E_FREE(e);
11736 }
11737
11738 static void
11739 _e_border_event_border_stack_free(void *data __UNUSED__,
11740                                   void      *ev)
11741 {
11742    E_Event_Border_Stack *e;
11743
11744    e = ev;
11745 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
11746    e_object_unref(E_OBJECT(e->border));
11747    if (e->stack)
11748      {
11749 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
11750           e_object_unref(E_OBJECT(e->stack));
11751      }
11752    E_FREE(e);
11753 }
11754
11755 static void
11756 _e_border_event_border_icon_change_free(void *data __UNUSED__,
11757                                         void      *ev)
11758 {
11759    E_Event_Border_Icon_Change *e;
11760
11761    e = ev;
11762 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
11763    e_object_unref(E_OBJECT(e->border));
11764    E_FREE(e);
11765 }
11766
11767 static void
11768 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
11769                                           void      *ev)
11770 {
11771    E_Event_Border_Urgent_Change *e;
11772
11773    e = ev;
11774    e_object_unref(E_OBJECT(e->border));
11775    E_FREE(e);
11776 }
11777
11778 static void
11779 _e_border_event_border_focus_in_free(void *data __UNUSED__,
11780                                      void      *ev)
11781 {
11782    E_Event_Border_Focus_In *e;
11783
11784    e = ev;
11785    e_object_unref(E_OBJECT(e->border));
11786    E_FREE(e);
11787 }
11788
11789 static void
11790 _e_border_event_border_focus_out_free(void *data __UNUSED__,
11791                                       void      *ev)
11792 {
11793    E_Event_Border_Focus_Out *e;
11794
11795    e = ev;
11796    e_object_unref(E_OBJECT(e->border));
11797    E_FREE(e);
11798 }
11799
11800 static void
11801 _e_border_event_border_property_free(void *data __UNUSED__,
11802                                      void      *ev)
11803 {
11804    E_Event_Border_Property *e;
11805
11806    e = ev;
11807    e_object_unref(E_OBJECT(e->border));
11808    E_FREE(e);
11809 }
11810
11811 static void
11812 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
11813                                        void      *ev)
11814 {
11815    E_Event_Border_Fullscreen *e;
11816
11817    e = ev;
11818 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
11819    e_object_unref(E_OBJECT(e->border));
11820    E_FREE(e);
11821 }
11822
11823 static void
11824 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
11825                                          void      *ev)
11826 {
11827    E_Event_Border_Unfullscreen *e;
11828
11829    e = ev;
11830 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
11831    e_object_unref(E_OBJECT(e->border));
11832    E_FREE(e);
11833 }
11834
11835 #ifdef _F_ZONE_WINDOW_ROTATION_
11836 static void
11837 _e_border_event_border_rotation_change_begin_free(void *data __UNUSED__,
11838                                                   void      *ev)
11839 {
11840    E_Event_Border_Rotation_Change_Begin *e;
11841    e = ev;
11842    e_object_unref(E_OBJECT(e->border));
11843    E_FREE(e);
11844 }
11845
11846 static void
11847 _e_border_event_border_rotation_change_cancel_free(void *data __UNUSED__,
11848                                                    void      *ev)
11849 {
11850    E_Event_Border_Rotation_Change_Cancel *e;
11851    e = ev;
11852    e_object_unref(E_OBJECT(e->border));
11853    E_FREE(e);
11854 }
11855
11856 static void
11857 _e_border_event_border_rotation_change_end_free(void *data __UNUSED__,
11858                                                 void      *ev)
11859 {
11860    E_Event_Border_Rotation_Change_End *e;
11861    e = ev;
11862    e_object_unref(E_OBJECT(e->border));
11863    E_FREE(e);
11864 }
11865
11866 static void
11867 _e_border_event_border_rotation_change_begin_send(E_Border *bd)
11868 {
11869    E_Event_Border_Rotation_Change_Begin *ev = NULL;
11870    ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
11871    if (ev)
11872      {
11873         ev->border = bd;
11874         e_object_ref(E_OBJECT(bd));
11875         ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_BEGIN,
11876                         ev,
11877                         _e_border_event_border_rotation_change_begin_free,
11878                         NULL);
11879      }
11880 }
11881 #endif
11882
11883 static void
11884 _e_border_zone_update(E_Border *bd)
11885 {
11886    E_Container *con;
11887    Eina_List *l;
11888    E_Zone *zone;
11889
11890    /* still within old zone - leave it there */
11891    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
11892                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
11893 #if _F_BORDER_CLIP_TO_ZONE_
11894      {
11895         _e_border_shape_input_clip_to_zone(bd);
11896         return;
11897      }
11898 #else
11899      return;
11900 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
11901    /* find a new zone */
11902    con = bd->zone->container;
11903    EINA_LIST_FOREACH(con->zones, l, zone)
11904      {
11905         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
11906                          zone->x, zone->y, zone->w, zone->h))
11907           {
11908              e_border_zone_set(bd, zone);
11909 #if _F_BORDER_CLIP_TO_ZONE_
11910              _e_border_shape_input_clip_to_zone(bd);
11911 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
11912              return;
11913           }
11914      }
11915 }
11916
11917 static int
11918 _e_border_resize_begin(E_Border *bd)
11919 {
11920    if (!bd->lock_user_stacking)
11921      {
11922         if (e_config->border_raise_on_mouse_action)
11923           e_border_raise(bd);
11924      }
11925    if ((bd->shaded) || (bd->shading) ||
11926        (bd->fullscreen) || (bd->lock_user_size))
11927      return 0;
11928
11929    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
11930      {
11931         grabbed = 0;
11932         return 0;
11933      }
11934
11935    if (bd->client.netwm.sync.request)
11936      {
11937         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
11938         bd->client.netwm.sync.serial = 1;
11939         bd->client.netwm.sync.wait = 0;
11940         bd->client.netwm.sync.send_time = ecore_loop_time_get();
11941      }
11942
11943    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
11944
11945    bdresize = bd;
11946    return 1;
11947 }
11948
11949 static int
11950 _e_border_resize_end(E_Border *bd)
11951 {
11952    if (grabbed)
11953      {
11954         e_grabinput_release(bd->win, bd->win);
11955         grabbed = 0;
11956      }
11957    if (bd->client.netwm.sync.alarm)
11958      {
11959         E_Border_Pending_Move_Resize *pnd;
11960
11961         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
11962         bd->client.netwm.sync.alarm = 0;
11963         /* resize to last geometry if sync alarm for it was not yet handled */
11964         if (bd->pending_move_resize)
11965           {
11966              bd->changed = 1;
11967              bd->changes.pos = 1;
11968              bd->changes.size = 1;
11969              _e_border_client_move_resize_send(bd);
11970           }
11971
11972         EINA_LIST_FREE(bd->pending_move_resize, pnd)
11973           E_FREE(pnd);
11974      }
11975
11976    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
11977
11978    bdresize = NULL;
11979
11980    /* If this border was maximized, we need to unset Maximized state or
11981     * on restart, E still thinks it's maximized */
11982    if (bd->maximized != E_MAXIMIZE_NONE)
11983      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
11984                                   bd->maximized & E_MAXIMIZE_NONE);
11985    return 1;
11986 }
11987
11988 static void
11989 _e_border_resize_update(E_Border *bd)
11990 {
11991    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
11992 }
11993
11994 static int
11995 _e_border_move_begin(E_Border *bd)
11996 {
11997    if (!bd->lock_user_stacking)
11998      {
11999         if (e_config->border_raise_on_mouse_action)
12000           e_border_raise(bd);
12001      }
12002    if ((bd->fullscreen) || (bd->lock_user_location))
12003      return 0;
12004
12005    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
12006      {
12007         grabbed = 0;
12008         return 0;
12009      }
12010 #if 0
12011    if (bd->client.netwm.sync.request)
12012      {
12013         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12014         bd->client.netwm.sync.serial = 0;
12015         bd->client.netwm.sync.wait = 0;
12016         bd->client.netwm.sync.time = ecore_loop_time_get();
12017      }
12018 #endif
12019    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
12020
12021    bdmove = bd;
12022    return 1;
12023 }
12024
12025 static int
12026 _e_border_move_end(E_Border *bd)
12027 {
12028    if (grabbed)
12029      {
12030         e_grabinput_release(bd->win, bd->win);
12031         grabbed = 0;
12032      }
12033 #if 0
12034    if (bd->client.netwm.sync.alarm)
12035      {
12036         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12037         bd->client.netwm.sync.alarm = 0;
12038      }
12039 #endif
12040    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
12041
12042    bdmove = NULL;
12043    return 1;
12044 }
12045
12046 static void
12047 _e_border_move_update(E_Border *bd)
12048 {
12049    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
12050 }
12051
12052 static Eina_Bool
12053 _e_border_cb_ping_poller(void *data)
12054 {
12055    E_Border *bd;
12056
12057    bd = data;
12058    if (bd->ping_ok)
12059      {
12060         if (bd->hung)
12061           {
12062              bd->hung = 0;
12063              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
12064              if (bd->kill_timer)
12065                {
12066                   ecore_timer_del(bd->kill_timer);
12067                   bd->kill_timer = NULL;
12068                }
12069           }
12070      }
12071    else
12072      {
12073         /* if time between last ping and now is greater
12074          * than half the ping interval... */
12075         if ((ecore_loop_time_get() - bd->ping) >
12076             ((e_config->ping_clients_interval *
12077               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
12078           {
12079              if (!bd->hung)
12080                {
12081                   bd->hung = 1;
12082                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
12083                   /* FIXME: if below dialog is up - hide it now */
12084                }
12085              if (bd->delete_requested)
12086                {
12087                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
12088                   e_border_act_kill_begin(bd);
12089                }
12090           }
12091      }
12092    bd->ping_poller = NULL;
12093    e_border_ping(bd);
12094    return ECORE_CALLBACK_CANCEL;
12095 }
12096
12097 static Eina_Bool
12098 _e_border_cb_kill_timer(void *data)
12099 {
12100    E_Border *bd;
12101
12102    bd = data;
12103 // dont wait until it's hung -
12104 //   if (bd->hung)
12105 //     {
12106         if (bd->client.netwm.pid > 1)
12107           kill(bd->client.netwm.pid, SIGKILL);
12108 //     }
12109    bd->kill_timer = NULL;
12110    return ECORE_CALLBACK_CANCEL;
12111 }
12112
12113 static void
12114 _e_border_pointer_resize_begin(E_Border *bd)
12115 {
12116    switch (bd->resize_mode)
12117      {
12118       case RESIZE_TL:
12119         e_pointer_type_push(bd->pointer, bd, "resize_tl");
12120         break;
12121
12122       case RESIZE_T:
12123         e_pointer_type_push(bd->pointer, bd, "resize_t");
12124         break;
12125
12126       case RESIZE_TR:
12127         e_pointer_type_push(bd->pointer, bd, "resize_tr");
12128         break;
12129
12130       case RESIZE_R:
12131         e_pointer_type_push(bd->pointer, bd, "resize_r");
12132         break;
12133
12134       case RESIZE_BR:
12135         e_pointer_type_push(bd->pointer, bd, "resize_br");
12136         break;
12137
12138       case RESIZE_B:
12139         e_pointer_type_push(bd->pointer, bd, "resize_b");
12140         break;
12141
12142       case RESIZE_BL:
12143         e_pointer_type_push(bd->pointer, bd, "resize_bl");
12144         break;
12145
12146       case RESIZE_L:
12147         e_pointer_type_push(bd->pointer, bd, "resize_l");
12148         break;
12149      }
12150 }
12151
12152 static void
12153 _e_border_pointer_resize_end(E_Border *bd)
12154 {
12155    switch (bd->resize_mode)
12156      {
12157       case RESIZE_TL:
12158         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
12159         break;
12160
12161       case RESIZE_T:
12162         e_pointer_type_pop(bd->pointer, bd, "resize_t");
12163         break;
12164
12165       case RESIZE_TR:
12166         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
12167         break;
12168
12169       case RESIZE_R:
12170         e_pointer_type_pop(bd->pointer, bd, "resize_r");
12171         break;
12172
12173       case RESIZE_BR:
12174         e_pointer_type_pop(bd->pointer, bd, "resize_br");
12175         break;
12176
12177       case RESIZE_B:
12178         e_pointer_type_pop(bd->pointer, bd, "resize_b");
12179         break;
12180
12181       case RESIZE_BL:
12182         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
12183         break;
12184
12185       case RESIZE_L:
12186         e_pointer_type_pop(bd->pointer, bd, "resize_l");
12187         break;
12188      }
12189 }
12190
12191 static void
12192 _e_border_pointer_move_begin(E_Border *bd)
12193 {
12194    e_pointer_type_push(bd->pointer, bd, "move");
12195 }
12196
12197 static void
12198 _e_border_pointer_move_end(E_Border *bd)
12199 {
12200    e_pointer_type_pop(bd->pointer, bd, "move");
12201 }
12202
12203 static Eina_List *_e_border_hooks = NULL;
12204 static int _e_border_hooks_delete = 0;
12205 static int _e_border_hooks_walking = 0;
12206
12207 static void
12208 _e_border_hooks_clean(void)
12209 {
12210    Eina_List *l, *ln;
12211    E_Border_Hook *bh;
12212
12213    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
12214      {
12215         if (bh->delete_me)
12216           {
12217              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
12218              free(bh);
12219           }
12220      }
12221 }
12222
12223 static void
12224 _e_border_hook_call(E_Border_Hook_Point hookpoint,
12225                     void               *bd)
12226 {
12227    Eina_List *l;
12228    E_Border_Hook *bh;
12229
12230    _e_border_hooks_walking++;
12231    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
12232      {
12233         if (bh->delete_me) continue;
12234         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
12235      }
12236    _e_border_hooks_walking--;
12237    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
12238      _e_border_hooks_clean();
12239 }
12240
12241 EAPI E_Border_Hook *
12242 e_border_hook_add(E_Border_Hook_Point               hookpoint,
12243                   void                              (*func)(void *data,
12244                                               void *bd),
12245                   void                             *data)
12246 {
12247    E_Border_Hook *bh;
12248
12249    bh = E_NEW(E_Border_Hook, 1);
12250    if (!bh) return NULL;
12251    bh->hookpoint = hookpoint;
12252    bh->func = func;
12253    bh->data = data;
12254    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
12255    return bh;
12256 }
12257
12258 EAPI void
12259 e_border_hook_del(E_Border_Hook *bh)
12260 {
12261    bh->delete_me = 1;
12262    if (_e_border_hooks_walking == 0)
12263      {
12264         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
12265         free(bh);
12266      }
12267    else
12268      _e_border_hooks_delete++;
12269 }
12270
12271 EAPI void
12272 e_border_focus_track_freeze(void)
12273 {
12274    focus_track_frozen++;
12275 }
12276
12277 EAPI void
12278 e_border_focus_track_thaw(void)
12279 {
12280    focus_track_frozen--;
12281 }
12282
12283 EAPI E_Border *
12284 e_border_under_pointer_get(E_Desk   *desk,
12285                            E_Border *exclude)
12286 {
12287    E_Border *bd = NULL, *cbd;
12288    Eina_List *l;
12289    int x, y;
12290
12291    /* We need to ensure that we can get the container window for the
12292     * zone of either the given desk or the desk of the excluded
12293     * window, so return if neither is given */
12294    if (desk)
12295      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
12296    else if (exclude)
12297      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
12298    else
12299      return NULL;
12300
12301    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
12302      {
12303         if (!cbd) continue;
12304         /* If a border was specified which should be excluded from the list
12305          * (because it will be closed shortly for example), skip */
12306         if ((exclude) && (cbd == exclude)) continue;
12307         if ((desk) && (cbd->desk != desk)) continue;
12308         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
12309           continue;
12310         /* If the layer is higher, the position of the window is higher
12311          * (always on top vs always below) */
12312         if (!bd || (cbd->layer > bd->layer))
12313           {
12314              bd = cbd;
12315              break;
12316           }
12317      }
12318    return bd;
12319 }
12320
12321 static Eina_Bool
12322 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
12323 {
12324    if (warp_to)
12325      {
12326         int x, y;
12327         double spd;
12328
12329         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
12330         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
12331             (y - warp_y) > 5 || (y - warp_y) < -5)
12332           {
12333              /* User moved the mouse, so stop warping */
12334              warp_to = 0;
12335              goto cleanup;
12336           }
12337
12338         /* We just use the same warp speed as configured
12339          * for the windowlist */
12340         spd = e_config->winlist_warp_speed;
12341         x = warp_x;
12342         y = warp_y;
12343         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12344         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12345         if (warp_x == x && warp_y == y)
12346           {
12347              warp_x = warp_to_x;
12348              warp_y = warp_to_y;
12349              warp_to = 0;
12350              goto cleanup;
12351           }
12352         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12353         return ECORE_CALLBACK_RENEW;
12354      }
12355  cleanup:
12356    ecore_timer_del(warp_timer);
12357    warp_timer = NULL;
12358    return ECORE_CALLBACK_CANCEL;
12359 }
12360
12361 EAPI int
12362 e_border_pointer_warp_to_center(E_Border *bd)
12363 {
12364    int x, y;
12365
12366    /* Do not slide pointer when disabled (probably breaks focus
12367     * on sloppy/mouse focus but requested by users). */
12368    if (!e_config->pointer_slide) return 0;
12369    /* Only warp the pointer if it is not already in the area of
12370     * the given border */
12371    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12372    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12373        (y >= bd->y) && (y <= (bd->y + bd->h)))
12374      return 0;
12375
12376    warp_to_x = bd->x + (bd->w / 2);
12377    if (warp_to_x < (bd->zone->x + 1))
12378      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12379    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12380      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12381
12382    warp_to_y = bd->y + (bd->h / 2);
12383    if (warp_to_y < (bd->zone->y + 1))
12384      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12385    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12386      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12387
12388    warp_to = 1;
12389    warp_to_win = bd->zone->container->win;
12390    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12391    if (!warp_timer)
12392      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12393    return 1;
12394 }
12395
12396 EAPI void
12397 e_border_comp_hidden_set(E_Border *bd,
12398                          Eina_Bool hidden)
12399 {
12400    E_Border *tmp;
12401    Eina_List *l;
12402
12403    E_OBJECT_CHECK(bd);
12404    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12405
12406    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12407      {
12408        if (hidden)
12409          ecore_x_window_hide(tmp->win);
12410        else
12411          ecore_x_window_show(tmp->win);
12412      }
12413
12414    if (bd->comp_hidden == hidden) return;
12415
12416    bd->comp_hidden = hidden;
12417
12418    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12419      {
12420         ecore_x_composite_window_events_disable(bd->win);
12421         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12422      }
12423    else
12424      {
12425         _e_border_shape_input_rectangle_set(bd);
12426         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12427      }
12428 }
12429
12430 EAPI void
12431 e_border_tmp_input_hidden_push(E_Border *bd)
12432 {
12433    E_Border *tmp;
12434    Eina_List *l;
12435
12436    E_OBJECT_CHECK(bd);
12437    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12438
12439    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12440      e_border_tmp_input_hidden_push(tmp);
12441
12442    bd->tmp_input_hidden++;
12443    if (bd->tmp_input_hidden != 1) return;
12444
12445    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12446      {
12447         ecore_x_composite_window_events_disable(bd->win);
12448         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12449      }
12450    else
12451      {
12452         _e_border_shape_input_rectangle_set(bd);
12453         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12454      }
12455 }
12456
12457 EAPI void
12458 e_border_tmp_input_hidden_pop(E_Border *bd)
12459 {
12460    E_Border *tmp;
12461    Eina_List *l;
12462
12463    E_OBJECT_CHECK(bd);
12464    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12465
12466    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12467      e_border_tmp_input_hidden_pop(tmp);
12468
12469    bd->tmp_input_hidden--;
12470    if (bd->tmp_input_hidden != 0) return;
12471
12472    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12473      {
12474         ecore_x_composite_window_events_disable(bd->win);
12475         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12476      }
12477    else
12478      {
12479         _e_border_shape_input_rectangle_set(bd);
12480         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12481      }
12482 }
12483
12484 EAPI void
12485 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
12486 {
12487    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
12488        ((bd->parent) &&
12489         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
12490          ((bd->parent->focused) &&
12491           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
12492        (just_do_it))
12493      {
12494         if (bd->iconic)
12495           {
12496              if (e_config->clientlist_warp_to_iconified_desktop == 1)
12497                e_desk_show(bd->desk);
12498              
12499              if (!bd->lock_user_iconify)
12500                e_border_uniconify(bd);
12501           }
12502         if ((!bd->iconic) && (!bd->sticky))
12503           e_desk_show(bd->desk);
12504         if (!bd->lock_user_stacking) e_border_raise(bd);
12505         if (!bd->lock_focus_out)
12506           {
12507              /* XXX ooffice does send this request for
12508               config dialogs when the main window gets focus.
12509               causing the pointer to jump back and forth.  */
12510              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
12511                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
12512                ecore_x_pointer_warp(bd->zone->container->win,
12513                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
12514              e_border_focus_set(bd, 1, 1);
12515           }
12516      }
12517 }
12518 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/