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