create rotation job and EAPI e_border_rotation_set
[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(4.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
8056         _e_border_event_border_rotation_change_begin_send(info->bd);
8057
8058         /* resize border */
8059         info->win_resize = _e_border_rotation_pre_resize(info->bd, info->ang, &x, &y, &w, &h);
8060         info->bd->client.e.state.rot.pending_change_request = info->win_resize;
8061
8062         info->x = x; info->y = y;
8063         info->w = w; info->h = h;
8064
8065         ELBF(ELBT_ROT, 1, info->bd->client.win,
8066              "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
8067              info->ang, info->win_resize, info->w, info->h);
8068
8069         ecore_x_e_window_rotation_change_prepare_send
8070            (info->bd->client.win, info->ang,
8071             info->win_resize, info->w, info->h);
8072
8073         if (!info->bd->client.e.state.rot.pending_change_request)
8074           {
8075              ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
8076              ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
8077                                                            info->ang);
8078              info->bd->client.e.state.rot.wait_for_done = EINA_TRUE;
8079           }
8080      }
8081
8082    if (flush)
8083      {
8084         EINA_LIST_FREE(list, info)
8085            E_FREE(info);
8086      }
8087 }
8088
8089 EAPI void
8090 e_border_rotation_list_clear(E_Zone *zone, Eina_Bool send_request)
8091 {
8092    E_Border_Rotation_Info *info = NULL;
8093
8094    if (send_request) _e_border_rotation_change_request(zone);
8095    else
8096      {
8097         EINA_LIST_FREE(rot.list, info)
8098            E_FREE(info);
8099         rot.list = NULL;
8100      }
8101 }
8102
8103 static void
8104 _e_border_rotation_list_remove(E_Border *bd)
8105 {
8106    Eina_List *l = NULL;
8107    E_Border_Rotation_Info *info = NULL;
8108    E_Event_Border_Rotation_Change_End *ev = NULL;
8109    Eina_Bool found = EINA_FALSE;
8110
8111    if (!e_config->wm_win_rotation) return;
8112
8113    EINA_LIST_FOREACH(rot.list, l, info)
8114      {
8115         if (info->bd == bd)
8116           {
8117              rot.list = eina_list_remove(rot.list, info);
8118              E_FREE(info);
8119              found = EINA_TRUE;
8120           }
8121      }
8122
8123    if (bd->client.e.state.rot.wait_for_done)
8124      {
8125         bd->client.e.state.rot.wait_for_done = 0;
8126
8127         /* if we make the border event in the _e_border_free function,
8128          * then we may meet a crash problem, only work this at least e_border_hide.
8129          */
8130         if (!e_object_is_del(E_OBJECT(bd)))
8131           {
8132              ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
8133              if (ev)
8134                {
8135                   ev->border = bd;
8136                   e_object_ref(E_OBJECT(bd));
8137                   ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_END,
8138                                   ev,
8139                                   _e_border_event_border_rotation_change_end_free,
8140                                   NULL);
8141                }
8142           }
8143
8144         if ((found) &&
8145             (eina_list_count(rot.list) == 0))
8146           {
8147              _e_border_rotation_change_done();
8148           }
8149      }
8150 }
8151
8152 static Eina_Bool
8153 _e_border_rotation_change_done_timeout(void *data __UNUSED__)
8154 {
8155    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8156    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE", 0);
8157    _e_border_rotation_change_done();
8158    return ECORE_CALLBACK_CANCEL;
8159 }
8160
8161 static void
8162 _e_border_rotation_change_done(void)
8163 {
8164    E_Manager *m = NULL;
8165    E_Border_Rotation_Info *info = NULL;
8166
8167    if (!e_config->wm_win_rotation) return;
8168
8169    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8170    rot.prepare_timer = NULL;
8171
8172    rot.wait_prepare_done = EINA_FALSE;
8173
8174    if (rot.done_timer) ecore_timer_del(rot.done_timer);
8175    rot.done_timer = NULL;
8176
8177    EINA_LIST_FREE(rot.list, info)
8178      {
8179         if (info->bd)
8180           {
8181              ELB(ELBT_ROT, "TIMEOUT ROT_DONE", info->bd->client.win);
8182              if (info->bd->client.e.state.rot.pending_show)
8183                {
8184                   ELB(ELBT_ROT, "SHOW PEND(TIMEOUT)", info->bd->client.win);
8185                   e_border_show(info->bd);
8186                   info->bd->client.e.state.rot.pending_show = 0;
8187                }
8188              info->bd->client.e.state.rot.wait_for_done = 0;
8189           }
8190         E_FREE(info);
8191      }
8192
8193    _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8194
8195    rot.list = NULL;
8196    rot.async_list = NULL;
8197
8198    m = e_manager_current_get();
8199    e_manager_comp_screen_unlock(m);
8200    e_zone_rotation_update_done(e_util_zone_current_get(m));
8201 }
8202
8203 static int
8204 _prev_angle_get(Ecore_X_Window win)
8205 {
8206    int ret, count = 0, ang = -1;
8207    unsigned char* data = NULL;
8208
8209    ret = ecore_x_window_prop_property_get
8210       (win, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
8211       ECORE_X_ATOM_CARDINAL, 32, &data, &count);
8212
8213    if ((ret) && (data) && (count))
8214      ang = ((int *)data)[0];
8215    if (data) free(data);
8216    return ang;
8217 }
8218
8219 /* get proper rotation value using preferred rotation and list of available rotations */
8220 static int
8221 _e_border_rotation_get(E_Border *bd,
8222                        int       base_ang)
8223 {
8224    int ang = -1;
8225    int current_ang = bd->client.e.state.rot.curr;
8226    unsigned int i;
8227    Eina_Bool found = EINA_FALSE;
8228    Eina_Bool found_curr_ang = EINA_FALSE;
8229
8230    if (!e_config->wm_win_rotation) return ang;
8231    if (!bd->client.e.state.rot.app_set) return ang;
8232
8233    if (bd->client.e.state.rot.preferred_rot != -1)
8234      {
8235         ang = bd->client.e.state.rot.preferred_rot;
8236         ELBF(ELBT_ROT, 0, bd->client.win, "ang:%d base_ang:%d", ang, base_ang);
8237      }
8238    else if ((bd->client.e.state.rot.available_rots) &&
8239             (bd->client.e.state.rot.count))
8240      {
8241         for (i = 0; i < bd->client.e.state.rot.count; i++)
8242           {
8243              if (bd->client.e.state.rot.available_rots[i] == base_ang)
8244                {
8245                   ang = base_ang;
8246                   found = EINA_TRUE;
8247                   break;
8248                }
8249              if (bd->client.e.state.rot.available_rots[i] == current_ang)
8250                found_curr_ang = EINA_TRUE;
8251           }
8252
8253         /* do nothing. this window wants to maintain current state.
8254          * for example, window's available_rots: 0, 90, 270,
8255          * current zone rotation request: 180. the WM does nothing
8256          * for this window.
8257          */
8258         if (!found)
8259           {
8260              if ((bd->client.e.state.rot.curr != -1) && (found_curr_ang))
8261                ang = bd->client.e.state.rot.curr;
8262              else
8263                ang = bd->client.e.state.rot.available_rots[0];
8264           }
8265      }
8266    else
8267      {
8268         /* In this case, border doesn't have a list of
8269          * available rotations, thus WM should request
8270          * rotation with '0' degree to the application.
8271          */
8272         ang = 0;
8273      }
8274
8275    return ang;
8276 }
8277
8278 static int
8279 _e_border_rotation_angle_get(E_Border *bd)
8280 {
8281    E_Zone *zone = bd->zone;
8282    int will_ang = 0;
8283    int _ang = 0;
8284    int ret = -1;
8285
8286    if (!e_config->wm_win_rotation) return ret;
8287    if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) return ret;
8288
8289    ELB(ELBT_ROT, "CHECK ROT", bd->client.win);
8290
8291    if (bd->parent) will_ang = bd->parent->client.e.state.rot.curr;
8292    else will_ang = zone->rot.curr;
8293
8294    if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
8295      {
8296         ELBF(ELBT_ROT, 1, bd->client.win,
8297              "%s->parent:0x%08x (support:%d app_set:%d ang:%d)",
8298              (rot.vkbd == bd) ? "vkbd" : "prediction",
8299              bd->parent ? bd->parent->client.win : 0,
8300              bd->parent ? bd->parent->client.e.state.rot.support : -1,
8301              bd->parent ? bd->parent->client.e.state.rot.app_set : -1,
8302              bd->parent ? bd->parent->client.e.state.rot.curr : -1);
8303
8304         if (bd->parent)
8305           {
8306              will_ang = bd->parent->client.e.state.rot.curr;
8307              if ((!bd->parent->client.e.state.rot.support) &&
8308                  (!bd->parent->client.e.state.rot.app_set))
8309                {
8310                   will_ang = 0;
8311                }
8312           }
8313      }
8314
8315    if ((!bd->client.e.state.rot.app_set) &&
8316        (!bd->client.e.state.rot.support))
8317      {
8318         /* hack for magnifier and keyboard popup */
8319         if ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER) ||
8320             (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP))
8321           {
8322              ELB(ELBT_BD, "MAG", bd->client.win);
8323              will_ang = 0;
8324              if ((rot.vkbd) && (rot.vkbd->visible))
8325                will_ang = rot.vkbd->client.e.state.rot.curr;
8326           }
8327      }
8328
8329    if (bd->client.e.state.rot.app_set)
8330      {
8331         /* utility type window should be rotated according to
8332          * rotation of the transient_for window.
8333          */
8334         if ((bd->parent) &&
8335             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
8336           {
8337              will_ang = bd->parent->client.e.state.rot.curr;
8338              if ((!bd->parent->client.e.state.rot.support) &&
8339                  (!bd->parent->client.e.state.rot.app_set))
8340                {
8341                   /* if transient_for window doesn't support rotation feature,
8342                    * then this window should't be rotated.
8343                    * TODO: need to check whether window supports '0' degree or not.
8344                    */
8345                   will_ang = 0;
8346                   ELBF(ELBT_ROT, 0, bd->client.win,
8347                        "GET ROT ang:%d Transient_For:0x%08x Not support rot",
8348                        will_ang, bd->parent->client.win);
8349                }
8350              else
8351                {
8352                   will_ang = _e_border_rotation_get(bd->parent, will_ang);
8353                   ELBF(ELBT_ROT, 0, bd->client.win,
8354                        "GET ROT ang:%d Transient_For:0x%08x",
8355                        will_ang, bd->parent->client.win);
8356                }
8357           }
8358         else
8359           {
8360              will_ang = _e_border_rotation_get(bd, will_ang);
8361              ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d",
8362                   will_ang, bd->parent ? bd->parent->client.win : 0,
8363                   bd->client.netwm.type);
8364           }
8365      }
8366
8367    if (bd->new_client)
8368      {
8369         _ang = _prev_angle_get(bd->client.win);
8370         if (_ang != -1)
8371           bd->client.e.state.rot.curr = _ang;
8372         ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang);
8373      }
8374
8375    if (bd->client.e.state.rot.curr != will_ang)
8376      ret = will_ang;
8377
8378    return ret;
8379 }
8380
8381
8382 static Eina_Bool
8383 _e_border_rotation_zone_set(E_Zone *zone)
8384 {
8385    E_Border_List *l = NULL;
8386    E_Border *bd = NULL;
8387    Eina_Bool ret = EINA_FALSE;
8388
8389    if (!e_config->wm_win_rotation) return EINA_FALSE;
8390
8391    l = e_container_border_list_last(zone->container);
8392    if (!l) return ret;
8393
8394    /* step 1. make the list needs to be rotated. */
8395    while ((bd = e_container_border_list_prev(l)))
8396      {
8397         if (!bd) continue;
8398
8399         // if this window have parent,
8400         // it will be rotated when parent do rotate itself.
8401         // so skip here.
8402         if (bd->parent) continue;
8403
8404         // this type is set by illume.
8405         // if it's not normal type window, will be rotated by illume.
8406         // so skip here.
8407         if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue;
8408
8409         if ((!bd->visible) ||
8410             (!E_INTERSECTS(bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h,
8411                            bd->x, bd->y, bd->w, bd->h))) continue;
8412
8413         if (_e_border_rotatable_check(bd, zone->rot.curr))
8414           {
8415              ELBF(ELBT_ROT, 0, bd->client.win, "ROT_SET(main) curr:%d != TOBE:%d",
8416                   bd->client.e.state.rot.curr, zone->rot.curr);
8417
8418              ret = e_border_rotation_set(bd, zone->rot.curr);
8419           }
8420      }
8421    if (l) e_container_border_list_free(l);
8422
8423    return ret;
8424 }
8425
8426 EAPI Eina_Bool
8427 e_border_rotation_set(E_Border *bd, int rotation)
8428 {
8429    E_Zone *zone = bd->zone;
8430    E_Border_Rotation_Info *info = NULL;
8431    Eina_List *list, *l;
8432    E_Border *child;
8433
8434    if (rotation < 0) return EINA_FALSE;
8435
8436    /* step 1. check if rotation */
8437    if (!_e_border_rotatable_check(bd, rotation)) return EINA_FALSE;
8438
8439    /* step 2. add to async/sync list */
8440    if ((!zone->rot.block_count) &&
8441        ((!bd->visible) ||
8442         (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))))
8443      {
8444         // send rotation change request later.
8445         // and no need to wait message of rotation done.
8446
8447         // async list add
8448         info = E_NEW(E_Border_Rotation_Info, 1);
8449         if (!info) return EINA_FALSE;
8450         ELB(ELBT_ROT, "ADD ASYNC LIST", 0);
8451         info->bd = bd;
8452         info->ang = rotation;
8453         rot.async_list = eina_list_append(rot.async_list, info);
8454
8455         // add job for sending event.
8456         if (!rot.async_job)
8457           {
8458              ELB(ELBT_ROT, "ADD ASYNC_JOB", bd->client.win);
8459              rot.async_job = ecore_job_add(_e_border_cb_rotation_async_job, zone);
8460           }
8461      }
8462    else
8463      {
8464         // sync list add
8465         info = E_NEW(E_Border_Rotation_Info, 1);
8466         if (!info) return EINA_FALSE;
8467         ELB(ELBT_ROT, "ADD SYNC LIST", 0);
8468         info->bd = bd;
8469         info->ang = rotation;
8470         rot.list = eina_list_append(rot.list, info);
8471
8472         // add job for sending event.
8473         if (!rot.sync_job)
8474           {
8475              ELB(ELBT_ROT, "ADD SYNC_JOB", bd->client.win);
8476              rot.sync_job = ecore_job_add(_e_border_cb_rotation_sync_job, zone);
8477           }
8478
8479         // if there is windows over 2 that has to be rotated or is existed window needs resizing,
8480         // lock the screen.
8481         // but, DO NOT lock the screen when rotation block state.
8482         if ((!zone->rot.block_count) &&
8483             ((eina_list_count(rot.list) == 2)))
8484           e_manager_comp_screen_lock(e_manager_current_get());
8485      }
8486
8487    /* step 3. search rotatable window in this window's child */
8488    list = _e_border_sub_borders_new(bd);
8489    EINA_LIST_FOREACH(list, l, child)
8490      {
8491         if (_e_border_rotatable_check(child, rotation))
8492           {
8493              ELBF(ELBT_ROT, 0, child->client.win, "ROT_SET(child) curr:%d != TOBE:%d",
8494                   bd->client.e.state.rot.curr, rotation);
8495              e_border_rotation_set(child, rotation);
8496           }
8497      }
8498
8499    /* step 4. if there is vkbd window, send message to prepare rotation */
8500    if (_e_border_is_vkbd(bd))
8501      {
8502         ELB(ELBT_ROT, "PENDING ROT_REQ UNTIL GET PREP_DONE", rot.vkbd_ctrl_win);
8503         if (rot.prepare_timer)
8504           ecore_timer_del(rot.prepare_timer);
8505         rot.prepare_timer = NULL;
8506
8507         if (rot.done_timer)
8508           ecore_timer_del(rot.done_timer);
8509         rot.done_timer = NULL;
8510
8511         ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win);
8512         ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8513                                                       zone->rot.curr,
8514                                                       EINA_FALSE, 1, 1);
8515         rot.prepare_timer = ecore_timer_add(4.0f,
8516                                             _e_border_rotation_change_prepare_timeout,
8517                                             NULL);
8518
8519         rot.wait_prepare_done = EINA_TRUE;
8520      }
8521
8522    bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8523    bd->client.e.state.rot.curr = rotation;
8524
8525    return EINA_TRUE;
8526 }
8527
8528 // check if border is rotatable in ang.
8529 static Eina_Bool
8530 _e_border_rotatable_check(E_Border *bd, int ang)
8531 {
8532    Eina_Bool ret = EINA_FALSE;
8533
8534    if (!bd) return ret;
8535    if (ang < 0) return ret;
8536    if ((!bd->client.e.state.rot.support) && (!bd->client.e.state.rot.app_set)) return ret;
8537    if (e_object_is_del(E_OBJECT(bd))) return ret;
8538
8539    // same with current angle of window, then false return.
8540    if (ang == bd->client.e.state.rot.curr) return ret;
8541
8542    /* basically WM allows only fullscreen window to rotate */
8543    if (bd->client.e.state.rot.preferred_rot == -1)
8544      {
8545         unsigned int i;
8546
8547         if (bd->client.e.state.rot.app_set)
8548           {
8549              if (bd->client.e.state.rot.available_rots &&
8550                  bd->client.e.state.rot.count)
8551                {
8552                   Eina_Bool found = EINA_FALSE;
8553                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8554                     {
8555                        if (bd->client.e.state.rot.available_rots[i] == ang)
8556                          {
8557                             found = EINA_TRUE;
8558                          }
8559                     }
8560                   if (found) ret = EINA_TRUE;
8561                }
8562           }
8563         else
8564           {
8565              ELB(ELBT_ROT, "DO ROT", 0);
8566              ret = EINA_TRUE;
8567           }
8568      }
8569    // if it has preferred rotation angle,
8570    // it will be rotated at border's evaluation time.
8571    // so skip it.
8572    else if (bd->client.e.state.rot.preferred_rot == ang) ret = EINA_TRUE;
8573
8574    return ret;
8575 }
8576
8577 /* check whether virtual keyboard is visible on the zone */
8578 static Eina_Bool
8579 _e_border_is_vkbd(E_Border *bd)
8580 {
8581    if (!e_config->wm_win_rotation) return EINA_FALSE;
8582
8583    if ((rot.vkbd_ctrl_win) &&
8584        (rot.vkbd == bd) &&
8585        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8586        (rot.vkbd->visible) &&
8587        (rot.vkbd->zone == bd->zone) &&
8588        (E_INTERSECTS(bd->zone->x, bd->zone->y,
8589                      bd->zone->w, bd->zone->h,
8590                      rot.vkbd->x, rot.vkbd->y,
8591                      rot.vkbd->w, rot.vkbd->h)))
8592      {
8593         return EINA_TRUE;
8594      }
8595    return EINA_FALSE;
8596 }
8597
8598 #define SIZE_EQUAL_TO_ZONE(a, z) \
8599    ((((a)->w) == ((z)->w)) &&    \
8600     (((a)->h) == ((z)->h)))
8601 static Eina_Bool
8602 _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h)
8603 {
8604    E_Zone *zone = bd->zone;
8605    int rot_dif;
8606    int _x, _y, _w, _h;
8607    Eina_Bool move = EINA_FALSE;
8608    Eina_Bool hint = EINA_FALSE;
8609    Eina_Bool resize = EINA_FALSE;
8610
8611    if (x) *x = bd->x;
8612    if (y) *y = bd->y;
8613    if (w) *w = bd->w;
8614    if (h) *h = bd->h;
8615
8616    if (SIZE_EQUAL_TO_ZONE(bd, zone)) return resize;
8617
8618    ELB(ELBT_ROT, "SIZE DIFF WITH ZONE", 0);
8619    ELBF(ELBT_ROT, 0, bd->client.win, "ORIGIN_SIZE name:%s (%d,%d) %dx%d",
8620         bd->client.icccm.name, bd->x, bd->y, bd->w, bd->h);
8621
8622    hint = _e_border_rotation_geom_get(bd, bd->zone, rotation,
8623                                       &_x, &_y, &_w, &_h, &move);
8624    if (hint)
8625      {
8626         _e_border_move_resize_internal(bd, _x, _y, _w, _h, EINA_TRUE, move);
8627         resize = EINA_TRUE;
8628         ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
8629              bd->client.icccm.name, _x, _y, _w, _h);
8630      }
8631    else
8632      {
8633         _x = bd->x; _y = bd->y;
8634         _w = bd->w; _h = bd->h;
8635
8636         rot_dif = bd->client.e.state.rot.curr - rotation;
8637         if (rot_dif < 0) rot_dif = -rot_dif;
8638         if (rot_dif != 180)
8639           {
8640              if (w != h)
8641                {
8642                   _w = bd->h;
8643                   _h = bd->w;
8644                   resize = EINA_TRUE;
8645
8646                   _e_border_move_resize_internal(bd, _x, _y, _w, _h,
8647                                                  EINA_TRUE, EINA_TRUE);
8648                   ELBF(ELBT_ROT, 0, bd->client.win, "MANUAL_RESIZE name:%s (%d,%d) %dx%d",
8649                        bd->client.icccm.name, _x, _y, _w, _h);
8650
8651                }
8652           }
8653      }
8654
8655    if (resize)
8656      {
8657         if (x) *x = _x;
8658         if (y) *y = _y;
8659         if (w) *w = _w;
8660         if (h) *h = _h;
8661      }
8662
8663    return resize;
8664 }
8665
8666 static Eina_Bool
8667 _e_border_cb_window_configure(void *data    __UNUSED__,
8668                               int   ev_type __UNUSED__,
8669                               void         *ev)
8670 {
8671    Ecore_X_Event_Window_Configure *e = ev;
8672    E_Border_Rotation_Info *info = NULL;
8673    Eina_List *l;
8674    Eina_Bool found = EINA_FALSE;
8675
8676    if (!e) return ECORE_CALLBACK_PASS_ON;
8677    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8678
8679    E_Border *bd = e_border_find_by_client_window(e->win);
8680    if (!bd) return ECORE_CALLBACK_PASS_ON;
8681
8682    if (bd->client.e.state.rot.pending_change_request)
8683      {
8684         if ((e->w == bd->w) && (e->h == bd->h))
8685           {
8686              ELB(ELBT_BD, "GET CONFIGURE_NOTI (ROTATION)", bd->client.win);
8687              bd->client.e.state.rot.pending_change_request = 0;
8688
8689              // if this window is rotation dependent window and zone is blocked to rotate,
8690              // then skip here, request will be sent after cancel block.
8691              if ((bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_DEPENDENT) &&
8692                  (bd->zone->rot.block_count)) goto end;
8693
8694              EINA_LIST_FOREACH(rot.list, l, info)
8695                 if (info->bd == bd) found = EINA_TRUE;
8696              // send request message if it's async rotation window,
8697              // even if wait prepare done.
8698              if ((found) && (rot.wait_prepare_done)) goto end;
8699
8700              ELBF(ELBT_ROT, 0, bd->client.win,
8701                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
8702                   bd->client.e.state.rot.curr,
8703                   bd->w, bd->h);
8704              ecore_x_e_window_rotation_change_request_send(bd->client.win,
8705                                                            bd->client.e.state.rot.curr);
8706              bd->client.e.state.rot.wait_for_done = EINA_TRUE;
8707           }
8708      }
8709
8710 end:
8711    return ECORE_CALLBACK_PASS_ON;
8712 }
8713
8714 static Eina_Bool
8715 _e_border_rotation_geom_get(E_Border  *bd,
8716                             E_Zone    *zone,
8717                             int        ang,
8718                             int       *x,
8719                             int       *y,
8720                             int       *w,
8721                             int       *h,
8722                             Eina_Bool *move)
8723 {
8724    if (!e_config->wm_win_rotation) return EINA_FALSE;
8725
8726    Eina_Bool res = EINA_FALSE;
8727    Eina_Bool _move = EINA_TRUE;
8728    int _x = bd->x;
8729    int _y = bd->y;
8730    int _w = bd->w;
8731    int _h = bd->h;
8732
8733    if (x) *x = bd->x;
8734    if (y) *y = bd->y;
8735    if (w) *w = bd->w;
8736    if (h) *h = bd->h;
8737    if (move) *move = EINA_TRUE;
8738
8739    if (bd->client.e.state.rot.geom_hint)
8740      {
8741         switch (ang)
8742           {
8743            case   0:
8744               _w = bd->client.e.state.rot.geom[0].w;
8745               _h = bd->client.e.state.rot.geom[0].h;
8746               if (_w == 0) _w = bd->w;
8747               if (_h == 0) _h = bd->h;
8748               _x = 0; _y = zone->h - _h;
8749               break;
8750            case  90:
8751               _w = bd->client.e.state.rot.geom[1].w;
8752               _h = bd->client.e.state.rot.geom[1].h;
8753               if (_w == 0) _w = bd->w;
8754               if (_h == 0) _h = bd->h;
8755               _x = zone->w - _w; _y = 0;
8756               break;
8757            case 180:
8758               _w = bd->client.e.state.rot.geom[2].w;
8759               _h = bd->client.e.state.rot.geom[2].h;
8760               if (_w == 0) _w = bd->w;
8761               if (_h == 0) _h = bd->h;
8762               _x = 0; _y = 0;
8763               break;
8764            case 270:
8765               _w = bd->client.e.state.rot.geom[3].w;
8766               _h = bd->client.e.state.rot.geom[3].h;
8767               if (_w == 0) _w = bd->w;
8768               if (_h == 0) _h = bd->h;
8769               _x = 0; _y = 0;
8770               break;
8771           }
8772
8773         if (x) *x = _x;
8774         if (y) *y = _y;
8775         if (w) *w = _w;
8776         if (h) *h = _h;
8777
8778         if (!((rot.vkbd) && (rot.vkbd == bd)))
8779           {
8780              if (x) *x = bd->x;
8781              if (y) *y = bd->y;
8782              if (move) *move = EINA_FALSE;
8783           }
8784
8785         res = EINA_TRUE;
8786      }
8787
8788    if (res)
8789      {
8790         _x = 0; _y = 0; _w = 0; _h = 0;
8791         if (x) _x = *x;
8792         if (y) _y = *y;
8793         if (w) _w = *w;
8794         if (h) _h = *h;
8795         if (move) _move = *move;
8796
8797         ELBF(ELBT_ROT, 1, bd->client.win,
8798              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
8799              ang, _x, _y, _w, _h, _move);
8800      }
8801
8802    return res;
8803 }
8804 #endif
8805
8806 static Eina_Bool
8807 _e_border_post_move_resize_job(void *data)
8808 {
8809    E_Border *bd;
8810
8811    bd = (E_Border *)data;
8812    if (bd->post_move)
8813      {
8814         E_Border *tmp;
8815         Eina_List *l;
8816
8817         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
8818           ecore_x_window_move(tmp->win,
8819                               bd->x +
8820                               bd->client_inset.l +
8821                               bd->fx.x +
8822                               tmp->client.e.state.video_position.x,
8823                               bd->y +
8824                               bd->client_inset.t +
8825                               bd->fx.y +
8826                               tmp->client.e.state.video_position.y);
8827      }
8828    if (bd->client.e.state.video)
8829      {
8830         E_Border *parent;
8831
8832         parent = bd->client.e.state.video_parent_border;
8833         ecore_x_window_move(bd->win,
8834                             parent->x +
8835                             parent->client_inset.l +
8836                             parent->fx.x +
8837                             bd->client.e.state.video_position.x,
8838                             parent->y +
8839                             parent->client_inset.t +
8840                             parent->fx.y +
8841                             bd->client.e.state.video_position.y);
8842      }
8843    else if ((bd->post_move) && (bd->post_resize))
8844      {
8845         ecore_x_window_move_resize(bd->win,
8846                                    bd->x + bd->fx.x,
8847                                    bd->y + bd->fx.y,
8848                                    bd->w, bd->h);
8849      }
8850    else if (bd->post_move)
8851      {
8852         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
8853      }
8854    else if (bd->post_resize)
8855      {
8856         ecore_x_window_resize(bd->win, bd->w, bd->h);
8857      }
8858
8859    if (bd->client.e.state.video)
8860      {
8861         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
8862                 bd->win,
8863                 bd->client.e.state.video_parent_border->x +
8864                 bd->client.e.state.video_parent_border->client_inset.l +
8865                 bd->client.e.state.video_parent_border->fx.x +
8866                 bd->client.e.state.video_position.x,
8867                 bd->client.e.state.video_parent_border->y +
8868                 bd->client.e.state.video_parent_border->client_inset.t +
8869                 bd->client.e.state.video_parent_border->fx.y +
8870                 bd->client.e.state.video_position.y,
8871                 bd->w, bd->h);
8872      }
8873
8874    if (bd->post_show)
8875      {
8876         if (bd->visible)
8877           {
8878              bd->post_job = NULL;
8879              _e_border_show(bd);
8880           }
8881      }
8882    bd->post_show = 0;
8883    bd->post_move = 0;
8884    bd->post_resize = 0;
8885    bd->post_job = NULL;
8886    return ECORE_CALLBACK_CANCEL;
8887 }
8888
8889 static void
8890 _e_border_container_layout_hook(E_Container *con)
8891 {
8892    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
8893 }
8894
8895 static void
8896 _e_border_eval0(E_Border *bd)
8897 {
8898    int change_urgent = 0;
8899    int rem_change = 0;
8900 #ifdef _F_USE_DESK_WINDOW_PROFILE_
8901    Eina_Bool need_desk_set = EINA_FALSE;
8902 #endif
8903 #ifdef _F_ZONE_WINDOW_ROTATION_
8904    Eina_Bool need_rotation_set = EINA_FALSE;
8905
8906    if ((e_config->wm_win_rotation) &&
8907        (bd->client.icccm.fetch.transient_for))
8908      {
8909         if (((rot.vkbd) && (rot.vkbd == bd)) ||
8910             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
8911           {
8912              need_rotation_set = EINA_TRUE;
8913              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
8914           }
8915      }
8916 #endif
8917
8918    if (e_object_is_del(E_OBJECT(bd)))
8919      {
8920         CRI("_e_border_eval(%p) with deleted border!\n", bd);
8921         bd->changed = 0;
8922         return;
8923      }
8924
8925    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
8926
8927    bd->changes.border = 0;
8928
8929    /* fetch any info queued to be fetched */
8930    if (bd->client.netwm.fetch.state)
8931      {
8932         e_hints_window_state_get(bd);
8933         bd->client.netwm.fetch.state = 0;
8934         rem_change = 1;
8935      }
8936    if (bd->client.icccm.fetch.client_leader)
8937      {
8938         /* TODO: What do to if the client leader isn't mapped yet? */
8939         E_Border *bd_leader = NULL;
8940
8941         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
8942         if (bd->client.icccm.client_leader)
8943           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
8944         if (bd->leader)
8945           {
8946              if (bd->leader != bd_leader)
8947                {
8948                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
8949                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
8950                   bd->leader = NULL;
8951                }
8952              else
8953                bd_leader = NULL;
8954           }
8955         /* If this border is the leader of the group, don't register itself */
8956         if ((bd_leader) && (bd_leader != bd))
8957           {
8958              bd_leader->group = eina_list_append(bd_leader->group, bd);
8959              bd->leader = bd_leader;
8960              /* Only set the window modal to the leader it there is no parent */
8961              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
8962                  ((!bd->parent) || (bd->parent->modal != bd)))
8963                {
8964                   bd->leader->modal = bd;
8965                   if (bd->leader->focused)
8966                     e_border_focus_set(bd, 1, 1);
8967                   else
8968                     {
8969                        Eina_List *l;
8970                        E_Border *child;
8971
8972                        EINA_LIST_FOREACH(bd->leader->group, l, child)
8973                          {
8974                             if ((child != bd) && (child->focused))
8975                               e_border_focus_set(bd, 1, 1);
8976                          }
8977                     }
8978                }
8979           }
8980         bd->client.icccm.fetch.client_leader = 0;
8981         rem_change = 1;
8982      }
8983    if (bd->client.icccm.fetch.title)
8984      {
8985         char *title = ecore_x_icccm_title_get(bd->client.win);
8986         eina_stringshare_replace(&bd->client.icccm.title, title);
8987         if (title) free(title);
8988
8989         if (bd->bg_object)
8990           edje_object_part_text_set(bd->bg_object, "e.text.title",
8991                                     bd->client.icccm.title);
8992         bd->client.icccm.fetch.title = 0;
8993         rem_change = 1;
8994      }
8995    if (bd->client.netwm.fetch.name)
8996      {
8997         char *name;
8998         ecore_x_netwm_name_get(bd->client.win, &name);
8999         eina_stringshare_replace(&bd->client.netwm.name, name);
9000         if (name) free(name);
9001
9002         if (bd->bg_object)
9003           edje_object_part_text_set(bd->bg_object, "e.text.title",
9004                                     bd->client.netwm.name);
9005         bd->client.netwm.fetch.name = 0;
9006         rem_change = 1;
9007      }
9008    if (bd->client.icccm.fetch.name_class)
9009      {
9010         const char *pname, *pclass;
9011         char *nname, *nclass;
9012
9013         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
9014         pname = bd->client.icccm.name;
9015         pclass = bd->client.icccm.class;
9016         bd->client.icccm.name = eina_stringshare_add(nname);
9017         bd->client.icccm.class = eina_stringshare_add(nclass);
9018         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
9019           e_bindings_mapping_change_enable(EINA_FALSE);
9020 #ifdef _F_ZONE_WINDOW_ROTATION_
9021         if (e_config->wm_win_rotation)
9022           {
9023              if ((bd->client.icccm.name) && (bd->client.icccm.class))
9024                {
9025                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
9026                       (!strcmp(bd->client.icccm.class, "ISF")))
9027                     {
9028                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
9029                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
9030                        rot.vkbd = bd;
9031                     }
9032                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
9033                            (!strcmp(bd->client.icccm.class, "ISF")))
9034                     {
9035                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
9036                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
9037                        rot.vkbd_prediction = bd;
9038                     }
9039                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
9040                            (!strcmp(bd->client.icccm.class, "ISF")))
9041                     {
9042                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
9043                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
9044                     }
9045                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
9046                            (!strcmp(bd->client.icccm.class, "ISF")))
9047                     {
9048                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
9049                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
9050                     }
9051                }
9052           }
9053 #endif
9054         if (nname) free(nname);
9055         if (nclass) free(nclass);
9056
9057         if (!((bd->client.icccm.name == pname) &&
9058               (bd->client.icccm.class == pclass)))
9059           bd->changes.icon = 1;
9060
9061         if (pname) eina_stringshare_del(pname);
9062         if (pclass) eina_stringshare_del(pclass);
9063         bd->client.icccm.fetch.name_class = 0;
9064         bd->changes.icon = 1;
9065         rem_change = 1;
9066      }
9067    if (bd->client.icccm.fetch.state)
9068      {
9069         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
9070         bd->client.icccm.fetch.state = 0;
9071         rem_change = 1;
9072      }
9073    if (bd->client.e.fetch.state)
9074      {
9075         e_hints_window_e_state_get(bd);
9076         bd->client.e.fetch.state = 0;
9077         rem_change = 1;
9078      }
9079 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9080    if (bd->client.e.fetch.profile_list)
9081      {
9082         const char **profiles = NULL;
9083         const char *str;
9084         int num = 0, i;
9085
9086         if (bd->client.e.state.profile)
9087           eina_stringshare_del(bd->client.e.state.profile);
9088         EINA_LIST_FREE(bd->client.e.state.profiles, str)
9089           {
9090              if (str) eina_stringshare_del(str);
9091           }
9092         bd->client.e.state.profile = NULL;
9093         bd->client.e.state.profiles = NULL;
9094         bd->client.e.state.profile_list = 0;
9095
9096         if (ecore_x_e_window_profile_list_get(bd->client.win,
9097                                               &profiles, &num))
9098           {
9099              bd->client.e.state.profile_list = 1;
9100              for (i = 0; i < num; i++)
9101                {
9102                   str = eina_stringshare_add(profiles[i]);
9103                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
9104                }
9105
9106              /* We should set desk to contain given border after creating E_BORDER_ADD event.
9107               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
9108               */
9109              need_desk_set = EINA_TRUE;
9110           }
9111         else
9112           {
9113              if (strcmp(bd->desk->window_profile,
9114                         e_config->desktop_default_window_profile) != 0)
9115                {
9116                   ecore_x_e_window_profile_set(bd->client.win,
9117                                                bd->desk->window_profile);
9118                }
9119           }
9120
9121         if (profiles)
9122           {
9123              for (i = 0; i < num; i++)
9124                 if (profiles[i]) free(profiles[i]);
9125              free(profiles);
9126           }
9127
9128         bd->client.e.fetch.profile_list = 0;
9129      }
9130 #endif
9131 #ifdef _F_ZONE_WINDOW_ROTATION_
9132    if ((e_config->wm_win_rotation) &&
9133        (bd->client.e.fetch.rot.support))
9134      {
9135         int ret = 0;
9136         unsigned int support = 0;
9137
9138         ret = ecore_x_window_prop_card32_get
9139           (bd->client.win,
9140           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
9141           &support, 1);
9142
9143         bd->client.e.state.rot.support = 0;
9144         if ((ret == 1) && (support == 1))
9145           bd->client.e.state.rot.support = 1;
9146
9147         if (bd->client.e.state.rot.support)
9148           need_rotation_set = EINA_TRUE;
9149
9150         bd->client.e.fetch.rot.support = 0;
9151      }
9152    if ((e_config->wm_win_rotation) &&
9153        (bd->client.e.fetch.rot.geom_hint))
9154      {
9155         Eina_Rectangle r[4];
9156         int i, x, y, w, h;
9157         bd->client.e.state.rot.geom_hint = 0;
9158         for (i = 0; i < 4; i++)
9159           {
9160              r[i].x = bd->client.e.state.rot.geom[i].x;
9161              r[i].y = bd->client.e.state.rot.geom[i].y;
9162              r[i].w = bd->client.e.state.rot.geom[i].w;
9163              r[i].h = bd->client.e.state.rot.geom[i].h;
9164
9165              bd->client.e.state.rot.geom[i].x = 0;
9166              bd->client.e.state.rot.geom[i].y = 0;
9167              bd->client.e.state.rot.geom[i].w = 0;
9168              bd->client.e.state.rot.geom[i].h = 0;
9169           }
9170
9171         for (i = 0; i < 4; i++)
9172           {
9173              x = 0; y = 0; w = 0; h = 0;
9174              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
9175                {
9176                   bd->client.e.state.rot.geom_hint = 1;
9177                   bd->client.e.state.rot.geom[i].x = x;
9178                   bd->client.e.state.rot.geom[i].y = y;
9179                   bd->client.e.state.rot.geom[i].w = w;
9180                   bd->client.e.state.rot.geom[i].h = h;
9181
9182                   if (!((r[i].x == x) && (r[i].y == y) &&
9183                         (r[i].w == w) && (r[i].h == h)))
9184                     {
9185                        need_rotation_set = EINA_TRUE;
9186                     }
9187                }
9188           }
9189         bd->client.e.fetch.rot.geom_hint = 0;
9190      }
9191    if ((e_config->wm_win_rotation) &&
9192        (bd->client.e.fetch.rot.app_set))
9193      {
9194         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
9195         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
9196         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
9197
9198         if (_prev_app_set != bd->client.e.state.rot.app_set)
9199           need_rotation_set = EINA_TRUE;
9200
9201         bd->client.e.fetch.rot.app_set = 0;
9202      }
9203    if ((e_config->wm_win_rotation) &&
9204        (bd->client.e.fetch.rot.preferred_rot))
9205      {
9206         int r = 0, _prev_preferred_rot;
9207         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
9208         bd->client.e.state.rot.preferred_rot = -1;
9209         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
9210           {
9211              bd->client.e.state.rot.preferred_rot = r;
9212              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
9213           }
9214         else
9215           {
9216              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
9217           }
9218
9219         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
9220           need_rotation_set = EINA_TRUE;
9221
9222         bd->client.e.fetch.rot.preferred_rot = 0;
9223      }
9224    if ((e_config->wm_win_rotation) &&
9225        (bd->client.e.fetch.rot.available_rots))
9226      {
9227         Eina_Bool res, diff = EINA_FALSE;
9228         int *rots = NULL;
9229         unsigned int count = 0, i = 0;
9230         int _prev_rots[4] = { -1, };
9231
9232         if (bd->client.e.state.rot.available_rots)
9233           {
9234              memcpy(_prev_rots,
9235                     bd->client.e.state.rot.available_rots,
9236                     (sizeof(int) * bd->client.e.state.rot.count));
9237
9238              E_FREE(bd->client.e.state.rot.available_rots);
9239           }
9240
9241         bd->client.e.state.rot.count = 0;
9242
9243         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
9244                                                                 &rots, &count);
9245         if ((res) && (count > 0) && (rots))
9246           {
9247              bd->client.e.state.rot.available_rots = rots;
9248              bd->client.e.state.rot.count = count;
9249
9250              for (i = 0; i < count; i++)
9251                {
9252                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
9253                   if ((!diff) && (_prev_rots[i] != rots[i]))
9254                     {
9255                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
9256                             count, i, _prev_rots[i], rots[i]);
9257                        diff = EINA_TRUE;
9258                     }
9259                }
9260           }
9261         else
9262           {
9263              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9264              diff = EINA_TRUE;
9265           }
9266
9267         if (diff) need_rotation_set = EINA_TRUE;
9268         bd->client.e.fetch.rot.available_rots = 0;
9269      }
9270 #endif
9271    if (bd->client.netwm.fetch.type)
9272      {
9273         e_hints_window_type_get(bd);
9274         if ((!bd->lock_border) || (!bd->client.border.name))
9275           bd->client.border.changed = 1;
9276
9277         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9278           {
9279              if (!bd->client.netwm.state.skip_pager)
9280                {
9281                   bd->client.netwm.state.skip_pager = 1;
9282                   bd->client.netwm.update.state = 1;
9283                }
9284              if (!bd->client.netwm.state.skip_taskbar)
9285                {
9286                   bd->client.netwm.state.skip_taskbar = 1;
9287                   bd->client.netwm.update.state = 1;
9288                }
9289           }
9290         bd->client.netwm.fetch.type = 0;
9291      }
9292    if (bd->client.icccm.fetch.machine)
9293      {
9294         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9295
9296         if ((!machine) && (bd->client.icccm.client_leader))
9297           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9298
9299         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9300         if (machine) free(machine);
9301
9302         bd->client.icccm.fetch.machine = 0;
9303         rem_change = 1;
9304      }
9305    if (bd->client.icccm.fetch.command)
9306      {
9307         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9308           {
9309              int i;
9310
9311              for (i = 0; i < bd->client.icccm.command.argc; i++)
9312                free(bd->client.icccm.command.argv[i]);
9313              free(bd->client.icccm.command.argv);
9314           }
9315         bd->client.icccm.command.argc = 0;
9316         bd->client.icccm.command.argv = NULL;
9317         ecore_x_icccm_command_get(bd->client.win,
9318                                   &(bd->client.icccm.command.argc),
9319                                   &(bd->client.icccm.command.argv));
9320         if ((bd->client.icccm.client_leader) &&
9321             (!bd->client.icccm.command.argv))
9322           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9323                                     &(bd->client.icccm.command.argc),
9324                                     &(bd->client.icccm.command.argv));
9325         bd->client.icccm.fetch.command = 0;
9326         rem_change = 1;
9327      }
9328    if (bd->client.icccm.fetch.hints)
9329      {
9330         Eina_Bool accepts_focus, is_urgent;
9331
9332         accepts_focus = EINA_TRUE;
9333         is_urgent = EINA_FALSE;
9334         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9335         if (ecore_x_icccm_hints_get(bd->client.win,
9336                                     &accepts_focus,
9337                                     &bd->client.icccm.initial_state,
9338                                     &bd->client.icccm.icon_pixmap,
9339                                     &bd->client.icccm.icon_mask,
9340                                     &bd->client.icccm.icon_window,
9341                                     &bd->client.icccm.window_group,
9342                                     &is_urgent))
9343           {
9344              bd->client.icccm.accepts_focus = accepts_focus;
9345              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9346                change_urgent = 1;
9347              bd->client.icccm.urgent = is_urgent;
9348
9349              /* If this is a new window, set the state as requested. */
9350              if ((bd->new_client) &&
9351                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9352                {
9353                   e_border_iconify(bd);
9354                   e_border_hide(bd, 1);
9355                }
9356           }
9357         bd->client.icccm.fetch.hints = 0;
9358         rem_change = 1;
9359      }
9360    if (bd->client.icccm.fetch.size_pos_hints)
9361      {
9362         Eina_Bool request_pos;
9363
9364         request_pos = EINA_FALSE;
9365         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9366                                              &request_pos,
9367                                              &bd->client.icccm.gravity,
9368                                              &bd->client.icccm.min_w,
9369                                              &bd->client.icccm.min_h,
9370                                              &bd->client.icccm.max_w,
9371                                              &bd->client.icccm.max_h,
9372                                              &bd->client.icccm.base_w,
9373                                              &bd->client.icccm.base_h,
9374                                              &bd->client.icccm.step_w,
9375                                              &bd->client.icccm.step_h,
9376                                              &bd->client.icccm.min_aspect,
9377                                              &bd->client.icccm.max_aspect))
9378           {
9379              bd->client.icccm.request_pos = request_pos;
9380           }
9381         else
9382           {
9383           }
9384         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9385         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9386         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9387         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9388         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9389         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9390         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9391         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9392         // if doing a resize, fix it up
9393         if (bd->resize_mode != RESIZE_NONE)
9394           {
9395              int x, y, w, h, new_w, new_h;
9396
9397              x = bd->x;
9398              y = bd->y;
9399              w = bd->w;
9400              h = bd->h;
9401              new_w = w;
9402              new_h = h;
9403              e_border_resize_limit(bd, &new_w, &new_h);
9404              if ((bd->resize_mode == RESIZE_TL) ||
9405                  (bd->resize_mode == RESIZE_L) ||
9406                  (bd->resize_mode == RESIZE_BL))
9407                x += (w - new_w);
9408              if ((bd->resize_mode == RESIZE_TL) ||
9409                  (bd->resize_mode == RESIZE_T) ||
9410                  (bd->resize_mode == RESIZE_TR))
9411                y += (h - new_h);
9412              e_border_move_resize(bd, x, y, new_w, new_h);
9413           }
9414         bd->client.icccm.fetch.size_pos_hints = 0;
9415         rem_change = 1;
9416      }
9417    if (bd->client.icccm.fetch.protocol)
9418      {
9419         int i, num;
9420         Ecore_X_WM_Protocol *proto;
9421
9422         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9423         if (proto)
9424           {
9425              for (i = 0; i < num; i++)
9426                {
9427                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9428                     bd->client.icccm.delete_request = 1;
9429                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9430                     bd->client.icccm.take_focus = 1;
9431                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9432                     bd->client.netwm.ping = 1;
9433                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9434                     {
9435                        bd->client.netwm.sync.request = 1;
9436                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9437                                                            &bd->client.netwm.sync.counter))
9438                          bd->client.netwm.sync.request = 0;
9439                     }
9440                }
9441              free(proto);
9442           }
9443         if (bd->client.netwm.ping)
9444           e_border_ping(bd);
9445         else
9446           {
9447              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9448              bd->ping_poller = NULL;
9449           }
9450         bd->client.icccm.fetch.protocol = 0;
9451      }
9452    if (bd->client.icccm.fetch.transient_for)
9453      {
9454         /* TODO: What do to if the transient for isn't mapped yet? */
9455         E_Border *bd_parent = NULL;
9456 #ifdef _F_DEICONIFY_APPROVE_
9457         Eina_Bool change_parent = EINA_FALSE;
9458 #endif
9459
9460         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9461         if (bd->client.icccm.transient_for)
9462           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9463         /* If we already have a parent, remove it */
9464         if (bd->parent)
9465           {
9466              if (bd_parent != bd->parent)
9467                {
9468                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9469                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9470                   bd->parent = NULL;
9471                }
9472              else
9473                bd_parent = NULL;
9474           }
9475         if ((bd_parent) && (bd_parent != bd) &&
9476             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9477           {
9478              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9479              bd->parent = bd_parent;
9480 #ifdef _F_DEICONIFY_APPROVE_
9481              change_parent = EINA_TRUE;
9482 #endif
9483           }
9484         if (bd->parent)
9485           {
9486              e_border_layer_set(bd, bd->parent->layer);
9487              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9488                {
9489                   Ecore_X_Window_Attributes attr;
9490                   bd->parent->modal = bd;
9491                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9492                   bd->parent->saved.event_mask = attr.event_mask.mine;
9493                   bd->parent->lock_close = 1;
9494                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9495                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9496                }
9497
9498              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9499                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9500                bd->take_focus = 1;
9501           }
9502
9503 #ifdef _F_DEICONIFY_APPROVE_
9504         if (change_parent)
9505           {
9506              bd->client.e.state.deiconify_approve.render_done = 0;
9507
9508              E_Border *ancestor_bd;
9509              ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
9510              if ((ancestor_bd) &&
9511                  (!e_object_is_del(E_OBJECT(ancestor_bd))))
9512                {
9513                   ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
9514                   bd->client.e.state.deiconify_approve.ancestor = NULL;
9515
9516                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
9517                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
9518                     {
9519                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
9520                          {
9521                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
9522                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
9523                             e_border_uniconify(ancestor_bd);
9524                          }
9525                     }
9526                }
9527           }
9528 #endif
9529         bd->client.icccm.fetch.transient_for = 0;
9530         rem_change = 1;
9531      }
9532    if (bd->client.icccm.fetch.window_role)
9533      {
9534         char *role = ecore_x_icccm_window_role_get(bd->client.win);
9535         eina_stringshare_replace(&bd->client.icccm.window_role, role);
9536         if (role) free(role);
9537
9538         bd->client.icccm.fetch.window_role = 0;
9539         rem_change = 1;
9540      }
9541    if (bd->client.icccm.fetch.icon_name)
9542      {
9543         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
9544         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
9545         if (icon_name) free(icon_name);
9546
9547         bd->client.icccm.fetch.icon_name = 0;
9548         rem_change = 1;
9549      }
9550    if (bd->client.netwm.fetch.icon_name)
9551      {
9552         char *icon_name;
9553         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
9554         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
9555         if (icon_name) free(icon_name);
9556
9557         bd->client.netwm.fetch.icon_name = 0;
9558         rem_change = 1;
9559      }
9560    if (bd->client.netwm.fetch.icon)
9561      {
9562         int i;
9563         if (bd->client.netwm.icons)
9564           {
9565              for (i = 0; i < bd->client.netwm.num_icons; i++)
9566                {
9567                   free(bd->client.netwm.icons[i].data);
9568                   bd->client.netwm.icons[i].data = NULL;
9569                }
9570              free(bd->client.netwm.icons);
9571           }
9572         bd->client.netwm.icons = NULL;
9573         bd->client.netwm.num_icons = 0;
9574         if (ecore_x_netwm_icons_get(bd->client.win,
9575                                      &bd->client.netwm.icons,
9576                                      &bd->client.netwm.num_icons))
9577           {
9578              // unless the rest of e17 uses border icons OTHER than icon #0
9579              // then free the rest that we don't need anymore.
9580              for (i = 1; i < bd->client.netwm.num_icons; i++)
9581                {
9582                   free(bd->client.netwm.icons[i].data);
9583                   bd->client.netwm.icons[i].data = NULL;
9584                }
9585              bd->client.netwm.num_icons = 1;
9586              bd->changes.icon = 1;
9587           }
9588         bd->client.netwm.fetch.icon = 0;
9589      }
9590    if (bd->client.netwm.fetch.user_time)
9591      {
9592         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
9593         bd->client.netwm.fetch.user_time = 0;
9594      }
9595    if (bd->client.netwm.fetch.strut)
9596      {
9597         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
9598                                              &bd->client.netwm.strut.left,
9599                                              &bd->client.netwm.strut.right,
9600                                              &bd->client.netwm.strut.top,
9601                                              &bd->client.netwm.strut.bottom,
9602                                              &bd->client.netwm.strut.left_start_y,
9603                                              &bd->client.netwm.strut.left_end_y,
9604                                              &bd->client.netwm.strut.right_start_y,
9605                                              &bd->client.netwm.strut.right_end_y,
9606                                              &bd->client.netwm.strut.top_start_x,
9607                                              &bd->client.netwm.strut.top_end_x,
9608                                              &bd->client.netwm.strut.bottom_start_x,
9609                                              &bd->client.netwm.strut.bottom_end_x))
9610           {
9611              ecore_x_netwm_strut_get(bd->client.win,
9612                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
9613                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
9614
9615              bd->client.netwm.strut.left_start_y = 0;
9616              bd->client.netwm.strut.left_end_y = 0;
9617              bd->client.netwm.strut.right_start_y = 0;
9618              bd->client.netwm.strut.right_end_y = 0;
9619              bd->client.netwm.strut.top_start_x = 0;
9620              bd->client.netwm.strut.top_end_x = 0;
9621              bd->client.netwm.strut.bottom_start_x = 0;
9622              bd->client.netwm.strut.bottom_end_x = 0;
9623           }
9624         bd->client.netwm.fetch.strut = 0;
9625      }
9626    if (bd->client.qtopia.fetch.soft_menu)
9627      {
9628         e_hints_window_qtopia_soft_menu_get(bd);
9629         bd->client.qtopia.fetch.soft_menu = 0;
9630         rem_change = 1;
9631      }
9632    if (bd->client.qtopia.fetch.soft_menus)
9633      {
9634         e_hints_window_qtopia_soft_menus_get(bd);
9635         bd->client.qtopia.fetch.soft_menus = 0;
9636         rem_change = 1;
9637      }
9638    if (bd->client.vkbd.fetch.state)
9639      {
9640         e_hints_window_virtual_keyboard_state_get(bd);
9641         bd->client.vkbd.fetch.state = 0;
9642         rem_change = 1;
9643      }
9644    if (bd->client.vkbd.fetch.vkbd)
9645      {
9646         e_hints_window_virtual_keyboard_get(bd);
9647         bd->client.vkbd.fetch.vkbd = 0;
9648         rem_change = 1;
9649      }
9650    if (bd->client.illume.conformant.fetch.conformant)
9651      {
9652         bd->client.illume.conformant.conformant =
9653           ecore_x_e_illume_conformant_get(bd->client.win);
9654         bd->client.illume.conformant.fetch.conformant = 0;
9655      }
9656    if (bd->client.illume.quickpanel.fetch.state)
9657      {
9658         bd->client.illume.quickpanel.state =
9659           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
9660         bd->client.illume.quickpanel.fetch.state = 0;
9661      }
9662    if (bd->client.illume.quickpanel.fetch.quickpanel)
9663      {
9664         bd->client.illume.quickpanel.quickpanel =
9665           ecore_x_e_illume_quickpanel_get(bd->client.win);
9666         bd->client.illume.quickpanel.fetch.quickpanel = 0;
9667      }
9668    if (bd->client.illume.quickpanel.fetch.priority.major)
9669      {
9670         bd->client.illume.quickpanel.priority.major =
9671           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
9672         bd->client.illume.quickpanel.fetch.priority.major = 0;
9673      }
9674    if (bd->client.illume.quickpanel.fetch.priority.minor)
9675      {
9676         bd->client.illume.quickpanel.priority.minor =
9677           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
9678         bd->client.illume.quickpanel.fetch.priority.minor = 0;
9679      }
9680    if (bd->client.illume.quickpanel.fetch.zone)
9681      {
9682         bd->client.illume.quickpanel.zone =
9683           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
9684         bd->client.illume.quickpanel.fetch.zone = 0;
9685      }
9686    if (bd->client.illume.drag.fetch.drag)
9687      {
9688         bd->client.illume.drag.drag =
9689           ecore_x_e_illume_drag_get(bd->client.win);
9690         bd->client.illume.drag.fetch.drag = 0;
9691      }
9692    if (bd->client.illume.drag.fetch.locked)
9693      {
9694         bd->client.illume.drag.locked =
9695           ecore_x_e_illume_drag_locked_get(bd->client.win);
9696         bd->client.illume.drag.fetch.locked = 0;
9697      }
9698    if (bd->client.illume.win_state.fetch.state)
9699      {
9700         bd->client.illume.win_state.state =
9701            ecore_x_e_illume_window_state_get(bd->client.win);
9702         bd->client.illume.win_state.fetch.state = 0;
9703      }
9704    if (bd->changes.shape)
9705      {
9706         Ecore_X_Rectangle *rects;
9707         int num;
9708
9709         bd->changes.shape = 0;
9710         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
9711         if (rects)
9712           {
9713              int cw = 0, ch = 0;
9714
9715              /* This doesn't fix the race, but makes it smaller. we detect
9716               * this and if cw and ch != client w/h then mark this as needing
9717               * a shape change again to fixup next event loop.
9718               */
9719              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9720              if ((cw != bd->client.w) || (ch != bd->client.h))
9721                bd->changes.shape = 1;
9722              if ((num == 1) &&
9723                  (rects[0].x == 0) &&
9724                  (rects[0].y == 0) &&
9725                  ((int)rects[0].width == cw) &&
9726                  ((int)rects[0].height == ch))
9727                {
9728                   if (bd->client.shaped)
9729                     {
9730                        bd->client.shaped = 0;
9731                        if (!bd->bordername)
9732                          bd->client.border.changed = 1;
9733                     }
9734                }
9735              else
9736                {
9737                   if (!bd->client.shaped)
9738                     {
9739                        bd->client.shaped = 1;
9740                        if (!bd->bordername)
9741                          bd->client.border.changed = 1;
9742                     }
9743                }
9744              free(rects);
9745           }
9746         else
9747           {
9748              // FIXME: no rects i think can mean... totally empty window
9749              bd->client.shaped = 0;
9750              if (!bd->bordername)
9751                bd->client.border.changed = 1;
9752           }
9753         bd->need_shape_merge = 1;
9754      }
9755    if (bd->changes.shape_input)
9756      {
9757         Ecore_X_Rectangle *rects;
9758         int num;
9759
9760         bd->changes.shape_input = 0;
9761         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
9762         if (rects)
9763           {
9764              int cw = 0, ch = 0;
9765
9766              /* This doesn't fix the race, but makes it smaller. we detect
9767               * this and if cw and ch != client w/h then mark this as needing
9768               * a shape change again to fixup next event loop.
9769               */
9770              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9771              if ((cw != bd->client.w) || (ch != bd->client.h))
9772                bd->changes.shape_input = 1;
9773              if ((num == 1) &&
9774                  (rects[0].x == 0) &&
9775                  (rects[0].y == 0) &&
9776                  ((int)rects[0].width == cw) &&
9777                  ((int)rects[0].height == ch))
9778                {
9779                   if (bd->shaped_input)
9780                     {
9781                        bd->shaped_input = 0;
9782                        if (!bd->bordername)
9783                          bd->client.border.changed = 1;
9784                     }
9785                }
9786              else
9787                {
9788                   if (!bd->shaped_input)
9789                     {
9790                        bd->shaped_input = 1;
9791                        if (!bd->bordername)
9792                          bd->client.border.changed = 1;
9793                     }
9794                }
9795              free(rects);
9796           }
9797         else
9798           {
9799              bd->shaped_input = 1;
9800              if (!bd->bordername)
9801                bd->client.border.changed = 1;
9802           }
9803         bd->need_shape_merge = 1;
9804      }
9805    if (bd->client.mwm.fetch.hints)
9806      {
9807         int pb;
9808
9809         bd->client.mwm.exists =
9810           ecore_x_mwm_hints_get(bd->client.win,
9811                                 &bd->client.mwm.func,
9812                                 &bd->client.mwm.decor,
9813                                 &bd->client.mwm.input);
9814         pb = bd->client.mwm.borderless;
9815         bd->client.mwm.borderless = 0;
9816         if (bd->client.mwm.exists)
9817           {
9818              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
9819                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
9820                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
9821                bd->client.mwm.borderless = 1;
9822           }
9823         if (bd->client.mwm.borderless != pb)
9824           {
9825              if ((!bd->lock_border) || (!bd->client.border.name))
9826                bd->client.border.changed = 1;
9827           }
9828         bd->client.mwm.fetch.hints = 0;
9829         rem_change = 1;
9830      }
9831    if (bd->client.e.fetch.video_parent)
9832      {
9833         /* unlinking child/parent */
9834         if (bd->client.e.state.video_parent_border != NULL)
9835           {
9836              bd->client.e.state.video_parent_border->client.e.state.video_child =
9837                eina_list_remove
9838                (bd->client.e.state.video_parent_border->client.e.state.video_child,
9839                    bd);
9840           }
9841
9842         ecore_x_window_prop_card32_get(bd->client.win,
9843                                        ECORE_X_ATOM_E_VIDEO_PARENT,
9844                                        &bd->client.e.state.video_parent,
9845                                        1);
9846
9847         /* linking child/parent */
9848         if (bd->client.e.state.video_parent != 0)
9849           {
9850              E_Border *tmp;
9851              Eina_List *l;
9852
9853              EINA_LIST_FOREACH(borders, l, tmp)
9854                if (tmp->client.win == bd->client.e.state.video_parent)
9855                  {
9856                     /* fprintf(stderr, "child added to parent \\o/\n"); */
9857                     bd->client.e.state.video_parent_border = tmp;
9858                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
9859                                                                        bd);
9860                     if (bd->desk != tmp->desk)
9861                       e_border_desk_set(bd, tmp->desk);
9862                     break;
9863                  }
9864           }
9865
9866         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
9867
9868         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
9869         rem_change = 1;
9870      }
9871    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
9872      {
9873         unsigned int xy[2];
9874
9875         ecore_x_window_prop_card32_get(bd->client.win,
9876                                        ECORE_X_ATOM_E_VIDEO_POSITION,
9877                                        xy,
9878                                        2);
9879         bd->client.e.state.video_position.x = xy[0];
9880         bd->client.e.state.video_position.y = xy[1];
9881         bd->client.e.state.video_position.updated = 1;
9882         bd->client.e.fetch.video_position = 0;
9883         bd->x = bd->client.e.state.video_position.x;
9884         bd->y = bd->client.e.state.video_position.y;
9885
9886         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
9887      }
9888    if (bd->client.netwm.update.state)
9889      {
9890         e_hints_window_state_set(bd);
9891         /* Some stats might change the border, like modal */
9892         if (((!bd->lock_border) || (!bd->client.border.name)) &&
9893             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
9894           {
9895              bd->client.border.changed = 1;
9896           }
9897         if (bd->parent)
9898           {
9899              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9900                {
9901                   bd->parent->modal = bd;
9902                   if (bd->parent->focused)
9903                     e_border_focus_set(bd, 1, 1);
9904                }
9905           }
9906         else if (bd->leader)
9907           {
9908              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9909                {
9910                   bd->leader->modal = bd;
9911                   if (bd->leader->focused)
9912                     e_border_focus_set(bd, 1, 1);
9913                   else
9914                     {
9915                        Eina_List *l;
9916                        E_Border *child;
9917
9918                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9919                          {
9920                             if ((child != bd) && (child->focused))
9921                               e_border_focus_set(bd, 1, 1);
9922                          }
9923                     }
9924                }
9925           }
9926         bd->client.netwm.update.state = 0;
9927      }
9928
9929    if (bd->new_client)
9930      {
9931         E_Event_Border_Add *ev;
9932         E_Exec_Instance *inst;
9933
9934         ev = E_NEW(E_Event_Border_Add, 1);
9935         ev->border = bd;
9936         e_object_ref(E_OBJECT(bd));
9937         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
9938         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
9939
9940         if ((!bd->lock_border) || (!bd->client.border.name))
9941           bd->client.border.changed = 1;
9942
9943           {
9944              char *str = NULL;
9945
9946              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
9947                  ((bd->client.icccm.client_leader > 0) &&
9948                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
9949                 )
9950                {
9951                   if (!strncmp(str, "E_START|", 8))
9952                     {
9953                        int id;
9954
9955                        id = atoi(str + 8);
9956                        if (id > 0) bd->client.netwm.startup_id = id;
9957                     }
9958                   free(str);
9959                }
9960           }
9961         /* It's ok not to have fetch flag, should only be set on startup
9962          *     * and not changed. */
9963         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
9964           {
9965              if (bd->client.icccm.client_leader)
9966                {
9967                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
9968                     bd->client.netwm.pid = -1;
9969                }
9970              else
9971                bd->client.netwm.pid = -1;
9972           }
9973
9974         if (!bd->re_manage)
9975           {
9976              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
9977                                                         bd->client.netwm.pid);
9978              if ((inst) && (inst->used == 0))
9979                {
9980                   E_Zone *zone;
9981                   E_Desk *desk;
9982
9983                   inst->used++;
9984                   zone = e_container_zone_number_get(bd->zone->container,
9985                                                      inst->screen);
9986                   if (zone) e_border_zone_set(bd, zone);
9987                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
9988                                           inst->desk_y);
9989                   if (desk) e_border_desk_set(bd, desk);
9990                   e_exec_instance_found(inst);
9991                }
9992
9993              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
9994                {
9995                   E_Border *bdl = NULL;
9996
9997                   bdl = bd->parent;
9998                   if (!bdl)
9999                     {
10000                        if (bd->leader) bdl = bd->leader;
10001                     }
10002                   if (!bdl)
10003                     {
10004                        E_Border *child;
10005                        E_Border_List *bl;
10006
10007                        bl = e_container_border_list_first(bd->zone->container);
10008                        while ((child = e_container_border_list_next(bl)))
10009                          {
10010                             if (child == bd) continue;
10011                             if (e_object_is_del(E_OBJECT(child))) continue;
10012                             if ((bd->client.icccm.client_leader) &&
10013                                 (child->client.icccm.client_leader ==
10014                                     bd->client.icccm.client_leader))
10015                               {
10016                                  bdl = child;
10017                                  break;
10018                               }
10019                          }
10020                        e_container_border_list_free(bl);
10021                     }
10022                   if (bdl)
10023                     {
10024                        if (bdl->zone)
10025                          e_border_zone_set(bd, bdl->zone);
10026                        if (bdl->desk)
10027                          e_border_desk_set(bd, bdl->desk);
10028                        else
10029                          e_border_stick(bd);
10030                     }
10031                }
10032           }
10033      }
10034
10035 #ifdef _F_USE_DESK_WINDOW_PROFILE_
10036    if (need_desk_set)
10037      {
10038         E_Container *con = bd->zone->container;
10039         E_Desk *desk = NULL;
10040         Eina_List *l;
10041         const char *str;
10042         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
10043           {
10044              desk = e_container_desk_window_profile_get(con, str);
10045              if (desk)
10046                {
10047                   if (bd->desk != desk)
10048                     {
10049                        bd->client.e.state.profile = eina_stringshare_add(str);
10050                        if (bd->zone != desk->zone)
10051                          e_border_zone_set(bd, desk->zone);
10052                        e_border_desk_set(bd, desk);
10053                     }
10054                   break;
10055                }
10056           }
10057      }
10058 #endif
10059
10060    /* PRE_POST_FETCH calls e_remember apply for new client */
10061    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
10062    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
10063    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
10064
10065 #ifdef _F_ZONE_WINDOW_ROTATION_
10066    if (e_config->wm_win_rotation)
10067      {
10068         if (need_rotation_set)
10069           {
10070              ELB(ELBT_ROT, "NEED ROT", bd->client.win);
10071              bd->client.e.state.rot.changes = _e_border_rotation_angle_get(bd);
10072              if (bd->client.e.state.rot.changes != -1) bd->changed = 1;
10073           }
10074
10075         if (bd->new_client)
10076           {
10077              Eina_Bool hint = EINA_FALSE;
10078              int ang = 0;
10079              int x, y, w, h, move;
10080
10081              if (bd->client.e.state.rot.changes != -1)
10082                ang = bd->client.e.state.rot.changes;
10083              else ang = bd->client.e.state.rot.curr;
10084
10085              hint = _e_border_rotation_geom_get(bd, bd->zone, ang, &x, &y, &w, &h, &move);
10086              if (hint)
10087                {
10088                   _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
10089                   ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
10090                        bd->client.icccm.name, x, y, w, h);
10091                }
10092           }
10093
10094      }
10095 #endif
10096
10097    if (bd->need_reparent)
10098      {
10099         if (!bd->internal)
10100           ecore_x_window_save_set_add(bd->client.win);
10101         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
10102         if (bd->visible)
10103           {
10104              if ((bd->new_client) && (bd->internal) &&
10105                  (bd->internal_ecore_evas))
10106                ecore_evas_show(bd->internal_ecore_evas);
10107              ecore_x_window_show(bd->client.win);
10108           }
10109         bd->need_reparent = 0;
10110      }
10111
10112    if ((bd->client.border.changed) && (!bd->shaded) &&
10113        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10114      {
10115         const char *bordername;
10116
10117         if (bd->fullscreen)
10118           bordername = "borderless";
10119         else if (bd->bordername)
10120           bordername = bd->bordername;
10121         else if ((bd->client.mwm.borderless) || (bd->borderless))
10122           bordername = "borderless";
10123         else if (((bd->client.icccm.transient_for != 0) ||
10124                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
10125                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10126                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10127           bordername = "noresize_dialog";
10128         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10129                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10130           bordername = "noresize";
10131         else if (bd->client.shaped)
10132           bordername = "shaped";
10133         else if ((!bd->client.icccm.accepts_focus) &&
10134                  (!bd->client.icccm.take_focus))
10135           bordername = "nofocus";
10136         else if (bd->client.icccm.urgent)
10137           bordername = "urgent";
10138         else if ((bd->client.icccm.transient_for != 0) ||
10139                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10140           bordername = "dialog";
10141         else if (bd->client.netwm.state.modal)
10142           bordername = "modal";
10143         else if ((bd->client.netwm.state.skip_taskbar) ||
10144                  (bd->client.netwm.state.skip_pager))
10145           bordername = "skipped";
10146         else if ((bd->internal) && (bd->client.icccm.class) &&
10147                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
10148           bordername = "internal_fileman";
10149         else
10150           bordername = e_config->theme_default_border_style;
10151         if (!bordername) bordername = "default";
10152
10153         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
10154           {
10155              Evas_Object *o;
10156              char buf[4096];
10157              int ok;
10158
10159              bd->changes.border = 1;
10160              eina_stringshare_replace(&bd->client.border.name, bordername);
10161
10162              if (bd->bg_object)
10163                {
10164                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
10165                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
10166                   bd->changes.size = 1;
10167                   evas_object_del(bd->bg_object);
10168                }
10169              o = edje_object_add(bd->bg_evas);
10170              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
10171              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10172              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
10173                {
10174                   if (bd->client.border.name != e_config->theme_default_border_style)
10175                     {
10176                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
10177                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10178                     }
10179                   if (!ok)
10180                     {
10181                        ok = e_theme_edje_object_set(o, "base/theme/borders",
10182                                                     "e/widgets/border/default/border");
10183                        if (ok)
10184                          {
10185                             /* Reset default border style to default */
10186                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
10187                             e_config_save_queue();
10188                          }
10189                     }
10190                }
10191
10192              bd->shaped = 0;
10193              if (ok)
10194                {
10195                   const char *shape_option, *argb_option;
10196                   int use_argb = 0;
10197
10198                   bd->bg_object = o;
10199
10200                   if ((e_config->use_composite) && (!bd->client.argb))
10201                     {
10202                        argb_option = edje_object_data_get(o, "argb");
10203                        if ((argb_option) && (!strcmp(argb_option, "1")))
10204                          use_argb = 1;
10205
10206                        if (use_argb != bd->argb)
10207                          _e_border_frame_replace(bd, use_argb);
10208
10209                        o = bd->bg_object;
10210                     }
10211
10212                   if (!bd->argb)
10213                     {
10214                        shape_option = edje_object_data_get(o, "shaped");
10215                        if ((shape_option) && (!strcmp(shape_option, "1")))
10216                          bd->shaped = 1;
10217                     }
10218
10219                   if (bd->client.netwm.name)
10220                     edje_object_part_text_set(o, "e.text.title",
10221                                               bd->client.netwm.name);
10222                   else if (bd->client.icccm.title)
10223                     edje_object_part_text_set(o, "e.text.title",
10224                                               bd->client.icccm.title);
10225                }
10226              else
10227                {
10228                   evas_object_del(o);
10229                   bd->bg_object = NULL;
10230                }
10231
10232              _e_border_client_inset_calc(bd);
10233
10234              bd->w += (bd->client_inset.l + bd->client_inset.r);
10235              bd->h += (bd->client_inset.t + bd->client_inset.b);
10236              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
10237              bd->changes.size = 1;
10238              /*  really needed ? */
10239              ecore_x_window_move(bd->client.shell_win,
10240                                  bd->client_inset.l,
10241                                  bd->client_inset.t);
10242
10243              if (bd->maximized != E_MAXIMIZE_NONE)
10244                {
10245                   E_Maximize maximized = bd->maximized;
10246
10247                   /* to force possible resizes */
10248                   bd->maximized = E_MAXIMIZE_NONE;
10249
10250                   _e_border_maximize(bd, maximized);
10251
10252                   /* restore maximized state */
10253                   bd->maximized = maximized;
10254
10255                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
10256                                                bd->maximized & E_MAXIMIZE_VERTICAL);
10257                }
10258              if (bd->bg_object)
10259                {
10260                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
10261                                                   _e_border_cb_signal_bind, bd);
10262                   if (bd->focused)
10263                     {
10264                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
10265                        if (bd->icon_object)
10266                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10267                     }
10268                   if (bd->shaded)
10269                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
10270                   if (bd->sticky)
10271                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
10272                   if (bd->hung)
10273                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
10274                   // FIXME: in eval -do differently
10275                   //         edje_object_message_signal_process(bd->bg_object);
10276                   //         e_border_frame_recalc(bd);
10277
10278                   evas_object_move(bd->bg_object, 0, 0);
10279                   evas_object_resize(bd->bg_object, bd->w, bd->h);
10280                   evas_object_show(bd->bg_object);
10281                }
10282           }
10283         bd->client.border.changed = 0;
10284
10285         if (bd->icon_object)
10286           {
10287              if (bd->bg_object)
10288                {
10289                   evas_object_show(bd->icon_object);
10290                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10291                }
10292              else
10293                evas_object_hide(bd->icon_object);
10294           }
10295      }
10296
10297    if (rem_change) e_remember_update(bd);
10298
10299    if (change_urgent)
10300      {
10301         E_Event_Border_Urgent_Change *ev;
10302
10303         if (bd->client.icccm.urgent)
10304           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
10305         else
10306           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
10307
10308         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
10309         ev->border = bd;
10310         e_object_ref(E_OBJECT(bd));
10311         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
10312                         _e_border_event_border_urgent_change_free, NULL);
10313      }
10314
10315    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10316 }
10317
10318 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10319 static void
10320 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10321 {
10322    E_Border* temp_bd = NULL;
10323    E_Border* top_focusable_bd = NULL;
10324    Eina_Bool is_fully_obscured = EINA_FALSE;
10325    Ecore_X_XRegion *visible_region = NULL;
10326    Ecore_X_XRegion *win_region = NULL;
10327    Ecore_X_Rectangle visible_rect, win_rect;
10328    E_Border_List *bl;
10329
10330    // set the entire visible region as a root geometry
10331    visible_rect.x = bd->zone->x;
10332    visible_rect.y = bd->zone->y;
10333    visible_rect.width = bd->zone->w;
10334    visible_rect.height = bd->zone->h;
10335
10336    visible_region = ecore_x_xregion_new();
10337    if (!visible_region) return;
10338
10339    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10340
10341    bl = e_container_border_list_last(bd->zone->container);
10342    while ((temp_bd = e_container_border_list_prev(bl)))
10343      {
10344         if (temp_bd == bd) break;
10345
10346         if (temp_bd == focused) continue;
10347         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10348         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10349         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10350             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10351             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10352             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10353             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10354             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10355             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10356           {
10357              if (!top_focusable_bd)
10358                {
10359                   top_focusable_bd = temp_bd;
10360                }
10361
10362              win_rect.x = temp_bd->x;
10363              win_rect.y = temp_bd->y;
10364              win_rect.width = temp_bd->w;
10365              win_rect.height = temp_bd->h;
10366
10367              // if it stick out or is bigger than the entire visible region,
10368              // clip it by the entire visible's geometry.
10369              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10370                                   win_rect.width, win_rect.height,
10371                                   visible_rect.x, visible_rect.y,
10372                                   (int)(visible_rect.width), (int)(visible_rect.height));
10373
10374              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10375                {
10376                   win_region = ecore_x_xregion_new();
10377                   if (win_region)
10378                     {
10379                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10380                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10381                        ecore_x_xregion_free(win_region);
10382                        win_region = NULL;
10383
10384                        if (ecore_x_xregion_is_empty(visible_region))
10385                          {
10386                             is_fully_obscured = EINA_TRUE;
10387                             break;
10388                          }
10389                     }
10390                }
10391           }
10392      }
10393
10394    if (is_fully_obscured == EINA_TRUE)
10395      {
10396         e_border_focus_set(top_focusable_bd, 1, 1);
10397      }
10398    else
10399      {
10400         e_border_focus_set(bd, 1, 1);
10401      }
10402
10403    if (visible_region) ecore_x_xregion_free(visible_region);
10404    e_container_border_list_free(bl);
10405 }
10406
10407 static void
10408 _e_border_latest_stacked_focus(E_Border *bd)
10409 {
10410    E_Border *temp_bd;
10411    int root_w, root_h;
10412
10413    root_w = bd->zone->w;
10414    root_h = bd->zone->h;
10415
10416    Eina_List *l;
10417    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10418      {
10419         if (bd == temp_bd) continue;
10420         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10421         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10422
10423         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10424             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10425             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10426             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10427             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10428             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10429             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10430           {
10431              _e_border_latest_stacked_focus_check_set(temp_bd);
10432              break;
10433           }
10434      }
10435 }
10436
10437 static void
10438 _e_border_check_stack (E_Border *bd)
10439 {
10440    E_Border* temp_bd = NULL;
10441    E_Border* top_bd = NULL;
10442    int passed_focus = 0;
10443    int passed = 0;
10444    int root_w = bd->zone->w;
10445    int root_h = bd->zone->h;
10446
10447    E_Border_List *bl;
10448    bl = e_container_border_list_last(bd->zone->container);
10449    while ((temp_bd = e_container_border_list_prev(bl)))
10450      {
10451         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10452         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10453         if ((temp_bd != bd) &&
10454             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10455
10456         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10457            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10458            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10459            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10460            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10461            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10462            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10463           {
10464              if (bd == temp_bd)
10465                {
10466                   if (!passed)
10467                     {
10468                        e_border_focus_set_with_pointer(bd);
10469                        break;
10470                     }
10471                   else
10472                     {
10473                        if (!passed_focus)
10474                          {
10475                             e_border_focus_set_with_pointer(top_bd);
10476                          }
10477                        break;
10478                     }
10479                }
10480              else
10481                {
10482                   if (!passed)
10483                     {
10484                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10485                          {
10486                             if (!bd->lock_focus_out)
10487                               {
10488                                  e_border_focus_latest_set(bd);
10489                               }
10490                          }
10491                     }
10492                }
10493
10494              if (!passed)
10495                {
10496                   passed = 1;
10497                   top_bd = temp_bd;
10498                }
10499
10500              if (temp_bd == focused)
10501                {
10502                   passed_focus = 1;
10503                }
10504           }
10505      }
10506    e_container_border_list_free(bl);
10507 }
10508
10509 static void
10510 _e_border_focus_top_stack_set(E_Border* bd)
10511 {
10512    E_Border *temp_bd;
10513    int root_w, root_h;
10514
10515    root_w = bd->zone->w;
10516    root_h = bd->zone->h;
10517
10518    E_Border_List *bl;
10519    bl = e_container_border_list_last(bd->zone->container);
10520    while ((temp_bd = e_container_border_list_prev(bl)))
10521      {
10522         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10523         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10524         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
10525
10526         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10527            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10528            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10529            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10530            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10531            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10532            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10533           {
10534              if (!temp_bd->focused)
10535                {
10536                   /* this border is the top of the latest stack */
10537                   e_border_focus_set (temp_bd, 1, 1);
10538                }
10539              break;
10540           }
10541      }
10542    e_container_border_list_free(bl);
10543 }
10544 #endif
10545
10546 static void
10547 _e_border_eval(E_Border *bd)
10548 {
10549    E_Event_Border_Property *event;
10550    E_Border_Pending_Move_Resize *pnd;
10551    int rem_change = 0;
10552    int send_event = 1;
10553
10554    if (e_object_is_del(E_OBJECT(bd)))
10555      {
10556         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
10557         bd->changed = 0;
10558         return;
10559      }
10560
10561    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
10562
10563    if (bd->new_client)
10564      {
10565         int zx = 0, zy = 0, zw = 0, zh = 0;
10566
10567         if (bd->zone)
10568           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
10569
10570         /*
10571          * Limit maximum size of windows to useful geometry
10572          */
10573         // TODO: temoporary limited maximize algorithm
10574         // ->
10575         /*if (bd->w > zw)
10576           rw = zw;
10577           else
10578           rw = bd->w;
10579
10580           if (bd->h > zh)
10581           rh = zh;
10582           else
10583           rh = bd->h;
10584
10585           if ((rw != bd->w) || (rh != bd->h))
10586           {
10587           bd->w = rw;
10588           bd->h = rh;
10589           e_border_resize (bd, bd->w, bd->h);
10590           }*/
10591         // <-
10592
10593         if (bd->re_manage)
10594           {
10595              bd->x -= bd->client_inset.l;
10596              bd->y -= bd->client_inset.t;
10597              bd->changes.pos = 1;
10598              bd->placed = 1;
10599           }
10600         else if ((!bd->placed) && (bd->client.icccm.request_pos))
10601           {
10602
10603              Ecore_X_Window_Attributes *att;
10604              int bw;
10605
10606              att = &bd->client.initial_attributes;
10607              bw = att->border * 2;
10608              switch (bd->client.icccm.gravity)
10609                {
10610                 case ECORE_X_GRAVITY_N:
10611                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10612                    bd->y = att->y;
10613                    break;
10614
10615                 case ECORE_X_GRAVITY_NE:
10616                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10617                    bd->y = att->y;
10618                    break;
10619
10620                 case ECORE_X_GRAVITY_E:
10621                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10622                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10623                    break;
10624
10625                 case ECORE_X_GRAVITY_SE:
10626                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10627                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10628                    break;
10629
10630                 case ECORE_X_GRAVITY_S:
10631                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10632                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10633                    break;
10634
10635                 case ECORE_X_GRAVITY_SW:
10636                    bd->x = att->x;
10637                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10638                    break;
10639
10640                 case ECORE_X_GRAVITY_W:
10641                    bd->x = att->x;
10642                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10643                    break;
10644
10645                 case ECORE_X_GRAVITY_CENTER:
10646                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10647                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10648                    break;
10649
10650                 case ECORE_X_GRAVITY_NW:
10651                 default:
10652                    bd->x = att->x;
10653                    bd->y = att->y;
10654                }
10655
10656              /*
10657               * This ensures that windows that like to open with a x/y
10658               * position smaller than returned by e_zone_useful_geometry_get()
10659               * are moved to useful positions.
10660               */
10661              // ->
10662              if (e_config->geometry_auto_move)
10663                {
10664                   if (bd->x < zx)
10665                     bd->x = zx;
10666
10667                   if (bd->y < zy)
10668                     bd->y = zy;
10669
10670                   if (bd->x + bd->w > zx + zw)
10671                     bd->x = zx + zw - bd->w;
10672
10673                   if (bd->y + bd->h > zy + zh)
10674                     bd->y = zy + zh - bd->h;
10675                   // <--
10676
10677                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
10678                     {
10679                        bd->changes.pos = 1;
10680                        bd->placed = 1;
10681                     }
10682                }
10683              else
10684                {
10685                   bd->changes.pos = 1;
10686                   bd->placed = 1;
10687                }
10688           }
10689         if (!bd->placed)
10690           {
10691              /* FIXME: special placement for dialogs etc. etc. etc goes
10692               * here */
10693              /* FIXME: what if parent is not on this desktop - or zone? */
10694              if ((bd->parent) && (bd->parent->visible))
10695                {
10696                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
10697                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
10698                   bd->changes.pos = 1;
10699                   bd->placed = 1;
10700                }
10701 #if 0
10702              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10703                {
10704                   /* TODO: Place in center of group */
10705                }
10706 #endif
10707              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
10708                {
10709                   bd->x = zx + ((zw - bd->w) / 2);
10710                   bd->y = zy + ((zh - bd->h) / 2);
10711                   bd->changes.pos = 1;
10712                   bd->placed = 1;
10713                }
10714           }
10715         if (!bd->placed)
10716           {
10717              Eina_List *skiplist = NULL;
10718              int new_x, new_y;
10719
10720              if (zw > bd->w)
10721                new_x = zx + (rand() % (zw - bd->w));
10722              else
10723                new_x = zx;
10724              if (zh > bd->h)
10725                new_y = zy + (rand() % (zh - bd->h));
10726              else
10727                new_y = zy;
10728
10729              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
10730                {
10731                   skiplist = eina_list_append(skiplist, bd);
10732                   if (bd->desk)
10733                     e_place_desk_region_smart(bd->desk, skiplist,
10734                                               bd->x, bd->y, bd->w, bd->h,
10735                                               &new_x, &new_y);
10736                   else
10737                     e_place_zone_region_smart(bd->zone, skiplist,
10738                                               bd->x, bd->y, bd->w, bd->h,
10739                                               &new_x, &new_y);
10740                   eina_list_free(skiplist);
10741                }
10742              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
10743                {
10744                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
10745                                       &new_x, &new_y);
10746                }
10747              else
10748                {
10749                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
10750                                       bd->client_inset.t, &new_x, &new_y);
10751                }
10752              bd->x = new_x;
10753              bd->y = new_y;
10754              bd->changes.pos = 1;
10755           }
10756
10757         EINA_LIST_FREE(bd->pending_move_resize, pnd)
10758           {
10759              if ((!bd->lock_client_location) && (pnd->move))
10760                {
10761                   bd->x = pnd->x;
10762                   bd->y = pnd->y;
10763                   bd->changes.pos = 1;
10764                   bd->placed = 1;
10765                   if (pnd->without_border)
10766                     {
10767                        bd->x -= bd->client_inset.l;
10768                        bd->y -= bd->client_inset.t;
10769                     }
10770                }
10771              if ((!bd->lock_client_size) && (pnd->resize))
10772                {
10773                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
10774                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
10775                   bd->client.w = pnd->w;
10776                   bd->client.h = pnd->h;
10777                   bd->changes.size = 1;
10778                }
10779
10780              free(pnd);
10781           }
10782
10783         /* Recreate state */
10784         e_hints_window_init(bd);
10785         if ((bd->client.e.state.centered) &&
10786             ((!bd->remember) ||
10787              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
10788           {
10789              bd->x = zx + (zw - bd->w) / 2;
10790              bd->y = zy + (zh - bd->h) / 2;
10791              bd->changes.pos = 1;
10792              bd->placed = 1;
10793           }
10794
10795         _e_border_client_move_resize_send(bd);
10796
10797         /* if the explicit geometry request asks for the app to be
10798          * in another zone - well move it there */
10799         {
10800            E_Zone *zone;
10801
10802            zone = e_container_zone_at_point_get(bd->zone->container,
10803                                                 bd->x + (bd->w / 2),
10804                                                 bd->y + (bd->h / 2));
10805            if (!zone)
10806              zone = e_container_zone_at_point_get(bd->zone->container,
10807                                                   bd->x,
10808                                                   bd->y);
10809            if (!zone)
10810              zone = e_container_zone_at_point_get(bd->zone->container,
10811                                                   bd->x + bd->w - 1,
10812                                                   bd->y);
10813            if (!zone)
10814              zone = e_container_zone_at_point_get(bd->zone->container,
10815                                                   bd->x + bd->w - 1,
10816                                                   bd->y + bd->h - 1);
10817            if (!zone)
10818              zone = e_container_zone_at_point_get(bd->zone->container,
10819                                                   bd->x,
10820                                                   bd->y + bd->h - 1);
10821            if ((zone) && (zone != bd->zone))
10822              e_border_zone_set(bd, zone);
10823         }
10824      }
10825
10826    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
10827
10828    /* effect changes to the window border itself */
10829    if ((bd->changes.shading))
10830      {
10831         /*  show at start of unshade (but don't hide until end of shade) */
10832         if (bd->shaded)
10833           ecore_x_window_raise(bd->client.shell_win);
10834         bd->changes.shading = 0;
10835         rem_change = 1;
10836      }
10837    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
10838      {
10839         if (bd->shaded)
10840           ecore_x_window_lower(bd->client.shell_win);
10841         else
10842           ecore_x_window_raise(bd->client.shell_win);
10843         bd->changes.shaded = 0;
10844         rem_change = 1;
10845      }
10846    else if ((bd->changes.shaded) && (bd->changes.pos))
10847      {
10848         if (bd->shaded)
10849           ecore_x_window_lower(bd->client.shell_win);
10850         else
10851           ecore_x_window_raise(bd->client.shell_win);
10852         bd->changes.size = 1;
10853         bd->changes.shaded = 0;
10854         rem_change = 1;
10855      }
10856    else if ((bd->changes.shaded) && (bd->changes.size))
10857      {
10858         if (bd->shaded)
10859           ecore_x_window_lower(bd->client.shell_win);
10860         else
10861           ecore_x_window_raise(bd->client.shell_win);
10862         bd->changes.shaded = 0;
10863         rem_change = 1;
10864      }
10865    else if (bd->changes.shaded)
10866      {
10867         if (bd->shaded)
10868           ecore_x_window_lower(bd->client.shell_win);
10869         else
10870           ecore_x_window_raise(bd->client.shell_win);
10871         bd->changes.size = 1;
10872         bd->changes.shaded = 0;
10873         rem_change = 1;
10874      }
10875
10876    if (bd->changes.size)
10877      {
10878         int x = 0, y = 0, xx = 0, yy = 0;
10879
10880         if ((bd->shaded) && (!bd->shading))
10881           {
10882              evas_obscured_clear(bd->bg_evas);
10883           }
10884         else
10885           {
10886              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
10887              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
10888
10889              evas_obscured_clear(bd->bg_evas);
10890              evas_obscured_rectangle_add(bd->bg_evas,
10891                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
10892
10893              if (bd->shading)
10894                {
10895                   if (bd->shade.dir == E_DIRECTION_UP)
10896                     {
10897                        y = yy - bd->client.h;
10898                     }
10899                   else if (bd->shade.dir == E_DIRECTION_LEFT)
10900                     {
10901                        x = xx - bd->client.w;
10902                     }
10903                }
10904           }
10905
10906         if (bd->client.e.state.video)
10907           {
10908              if (bd->client.e.state.video_position.updated)
10909                {
10910                   ecore_x_window_move(bd->win,
10911                                       bd->client.e.state.video_parent_border->x +
10912                                       bd->client.e.state.video_parent_border->client_inset.l +
10913                                       bd->client.e.state.video_parent_border->fx.x +
10914                                       bd->client.e.state.video_position.x,
10915                                       bd->client.e.state.video_parent_border->y +
10916                                       bd->client.e.state.video_parent_border->client_inset.t +
10917                                       bd->client.e.state.video_parent_border->fx.y +
10918                                       bd->client.e.state.video_position.y);
10919                   bd->client.e.state.video_position.updated = 0;
10920                }
10921           }
10922         else if (!bd->changes.pos)
10923           {
10924              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
10925              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
10926              bd->post_resize = 1;
10927           }
10928         else
10929           {
10930              E_Border *tmp;
10931              Eina_List *l;
10932
10933              ecore_x_window_move_resize(bd->win,
10934                                         bd->x + bd->fx.x,
10935                                         bd->y + bd->fx.y,
10936                                         bd->w, bd->h);
10937
10938              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
10939                ecore_x_window_move(tmp->win,
10940                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
10941                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
10942           }
10943
10944         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
10945
10946         if ((!bd->shaded) || (bd->shading))
10947           ecore_x_window_move_resize(bd->client.shell_win,
10948                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
10949
10950         if (bd->internal_ecore_evas)
10951           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
10952         else if (!bd->client.e.state.video)
10953           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
10954
10955         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
10956         evas_object_resize(bd->bg_object, bd->w, bd->h);
10957         e_container_shape_resize(bd->shape, bd->w, bd->h);
10958         if (bd->changes.pos)
10959           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
10960
10961         _e_border_client_move_resize_send(bd);
10962
10963         bd->changes.pos = 0;
10964         bd->changes.size = 0;
10965         rem_change = 1;
10966      }
10967    else if (bd->changes.pos)
10968      {
10969         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
10970         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
10971         bd->post_move = 1;
10972
10973         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
10974
10975         _e_border_client_move_resize_send(bd);
10976
10977         bd->changes.pos = 0;
10978         rem_change = 1;
10979      }
10980
10981    if (bd->changes.reset_gravity)
10982      {
10983         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
10984         bd->changes.reset_gravity = 0;
10985         rem_change = 1;
10986      }
10987
10988    if (bd->need_shape_merge)
10989      {
10990         _e_border_shape_input_rectangle_set(bd);
10991         if ((bd->shaped) || (bd->client.shaped))
10992           {
10993              Ecore_X_Window twin, twin2;
10994              int x, y;
10995
10996              twin = ecore_x_window_override_new
10997                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
10998              if (bd->shaped)
10999                ecore_x_window_shape_window_set(twin, bd->bg_win);
11000              else
11001                {
11002                   Ecore_X_Rectangle rects[4];
11003
11004                   rects[0].x = 0;
11005                   rects[0].y = 0;
11006                   rects[0].width = bd->w;
11007                   rects[0].height = bd->client_inset.t;
11008                   rects[1].x = 0;
11009                   rects[1].y = bd->client_inset.t;
11010                   rects[1].width = bd->client_inset.l;
11011                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11012                   rects[2].x = bd->w - bd->client_inset.r;
11013                   rects[2].y = bd->client_inset.t;
11014                   rects[2].width = bd->client_inset.r;
11015                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11016                   rects[3].x = 0;
11017                   rects[3].y = bd->h - bd->client_inset.b;
11018                   rects[3].width = bd->w;
11019                   rects[3].height = bd->client_inset.b;
11020                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
11021                }
11022              twin2 = ecore_x_window_override_new
11023                (bd->zone->container->scratch_win, 0, 0,
11024                 bd->w - bd->client_inset.l - bd->client_inset.r,
11025                 bd->h - bd->client_inset.t - bd->client_inset.b);
11026              x = 0;
11027              y = 0;
11028              if ((bd->shading) || (bd->shaded))
11029                {
11030                   if (bd->shade.dir == E_DIRECTION_UP)
11031                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
11032                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11033                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
11034                }
11035              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
11036                                                 x, y);
11037              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
11038                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
11039                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
11040              ecore_x_window_shape_window_add_xy(twin, twin2,
11041                                                 bd->client_inset.l,
11042                                                 bd->client_inset.t);
11043              ecore_x_window_free(twin2);
11044              ecore_x_window_shape_window_set(bd->win, twin);
11045              ecore_x_window_free(twin);
11046           }
11047         else
11048           ecore_x_window_shape_mask_set(bd->win, 0);
11049         //      bd->need_shape_export = 1;
11050         bd->need_shape_merge = 0;
11051      }
11052
11053    if (bd->need_shape_export)
11054      {
11055         Ecore_X_Rectangle *rects, *orects;
11056         int num;
11057
11058         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
11059         if (rects)
11060           {
11061              int changed;
11062
11063              changed = 1;
11064              if ((num == bd->shape_rects_num) && (bd->shape_rects))
11065                {
11066                   int i;
11067
11068                   orects = bd->shape_rects;
11069                   changed = 0;
11070                   for (i = 0; i < num; i++)
11071                     {
11072                        if (rects[i].x < 0)
11073                          {
11074                             rects[i].width -= rects[i].x;
11075                             rects[i].x = 0;
11076                          }
11077                        if ((rects[i].x + (int)rects[i].width) > bd->w)
11078                          rects[i].width = rects[i].width - rects[i].x;
11079                        if (rects[i].y < 0)
11080                          {
11081                             rects[i].height -= rects[i].y;
11082                             rects[i].y = 0;
11083                          }
11084                        if ((rects[i].y + (int)rects[i].height) > bd->h)
11085                          rects[i].height = rects[i].height - rects[i].y;
11086
11087                        if ((orects[i].x != rects[i].x) ||
11088                            (orects[i].y != rects[i].y) ||
11089                            (orects[i].width != rects[i].width) ||
11090                            (orects[i].height != rects[i].height))
11091                          {
11092                             changed = 1;
11093                             break;
11094                          }
11095                     }
11096                }
11097              if (changed)
11098                {
11099                   if (bd->client.shaped)
11100                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
11101                   else
11102                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
11103                   E_FREE(bd->shape_rects);
11104                   bd->shape_rects = rects;
11105                   bd->shape_rects_num = num;
11106                   e_container_shape_rects_set(bd->shape, rects, num);
11107                }
11108              else
11109                free(rects);
11110           }
11111         else
11112           {
11113              E_FREE(bd->shape_rects);
11114              bd->shape_rects = NULL;
11115              bd->shape_rects_num = 0;
11116              e_container_shape_rects_set(bd->shape, NULL, 0);
11117           }
11118         bd->need_shape_export = 0;
11119      }
11120
11121    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
11122      {
11123         int x, y;
11124
11125         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
11126         if ((!bd->placed) && (!bd->re_manage) &&
11127             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
11128             (!((bd->client.icccm.transient_for != 0) ||
11129                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
11130             (!bdmove) && (!bdresize))
11131           {
11132              /* Set this window into moving state */
11133
11134              bd->cur_mouse_action = e_action_find("window_move");
11135              if (bd->cur_mouse_action)
11136                {
11137                   if ((!bd->cur_mouse_action->func.end_mouse) &&
11138                       (!bd->cur_mouse_action->func.end))
11139                     bd->cur_mouse_action = NULL;
11140                   if (bd->cur_mouse_action)
11141                     {
11142                        bd->x = x - (bd->w >> 1);
11143                        bd->y = y - (bd->client_inset.t >> 1);
11144                        bd->changed = 1;
11145                        bd->changes.pos = 1;
11146
11147                        _e_border_client_move_resize_send(bd);
11148                     }
11149                }
11150           }
11151
11152         _e_border_show(bd);
11153
11154         if (bd->cur_mouse_action)
11155           {
11156              bd->moveinfo.down.x = bd->x + bd->fx.x;
11157              bd->moveinfo.down.y = bd->y + bd->fx.y;
11158              bd->moveinfo.down.w = bd->w;
11159              bd->moveinfo.down.h = bd->h;
11160              bd->mouse.current.mx = x;
11161              bd->mouse.current.my = y;
11162              bd->moveinfo.down.button = 0;
11163              bd->moveinfo.down.mx = x;
11164              bd->moveinfo.down.my = y;
11165
11166              grabbed = 1;
11167              e_object_ref(E_OBJECT(bd->cur_mouse_action));
11168              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
11169              if (e_config->border_raise_on_mouse_action)
11170                e_border_raise(bd);
11171              e_border_focus_set(bd, 1, 1);
11172           }
11173         bd->changes.visible = 0;
11174         rem_change = 1;
11175      }
11176
11177    if (bd->changes.icon)
11178      {
11179         if (bd->desktop)
11180           {
11181              efreet_desktop_free(bd->desktop);
11182              bd->desktop = NULL;
11183           }
11184         if (bd->icon_object)
11185           {
11186              evas_object_del(bd->icon_object);
11187              bd->icon_object = NULL;
11188           }
11189         if (bd->remember && bd->remember->prop.desktop_file)
11190           {
11191              const char *desktop = bd->remember->prop.desktop_file;
11192
11193              bd->desktop = efreet_desktop_get(desktop);
11194              if (!bd->desktop)
11195                bd->desktop = efreet_util_desktop_name_find(desktop);
11196           }
11197         if (!bd->desktop)
11198           {
11199              if ((bd->client.icccm.name) && (bd->client.icccm.class))
11200                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
11201                                                                bd->client.icccm.class);
11202           }
11203         if (!bd->desktop)
11204           {
11205              /* libreoffice and maybe others match window class
11206                 with .desktop file name */
11207              if (bd->client.icccm.class)
11208                {
11209                   char buf[128];
11210                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
11211                   bd->desktop = efreet_util_desktop_file_id_find(buf);
11212                }
11213           }
11214         if (!bd->desktop)
11215           {
11216              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
11217                                                       bd->client.netwm.pid);
11218              if (bd->desktop) efreet_desktop_ref(bd->desktop);
11219           }
11220         if (!bd->desktop && bd->client.icccm.name)
11221           {
11222              /* this works for most cases as fallback. useful when app is
11223                 run from a shell  */
11224              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
11225           }
11226         if (!bd->desktop && bd->client.icccm.transient_for)
11227           {
11228              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
11229              if (bd2 && bd2->desktop)
11230                {
11231                   efreet_desktop_ref(bd2->desktop);
11232                   bd->desktop = bd2->desktop;
11233                }
11234           }
11235         if (bd->desktop)
11236           {
11237              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
11238                                             bd->desktop->orig_path);
11239           }
11240
11241         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
11242         if ((bd->focused) && (bd->icon_object))
11243           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
11244         if (bd->bg_object)
11245           {
11246              evas_object_show(bd->icon_object);
11247              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
11248           }
11249         else
11250           evas_object_hide(bd->icon_object);
11251
11252         {
11253            E_Event_Border_Icon_Change *ev;
11254
11255            ev = E_NEW(E_Event_Border_Icon_Change, 1);
11256            ev->border = bd;
11257            e_object_ref(E_OBJECT(bd));
11258            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
11259            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
11260                            _e_border_event_border_icon_change_free, NULL);
11261         }
11262         bd->changes.icon = 0;
11263      }
11264
11265    bd->new_client = 0;
11266    bd->changed = 0;
11267    bd->changes.stack = 0;
11268    bd->changes.prop = 0;
11269
11270    if (bd->client.e.state.rot.changes != -1)
11271      {
11272         e_border_rotation_set(bd, bd->client.e.state.rot.changes);
11273         bd->client.e.state.rot.changes = -1;
11274      }
11275
11276    if ((bd->take_focus) || (bd->want_focus))
11277      {
11278         bd->take_focus = 0;
11279 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11280         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
11281             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
11282             (bd->want_focus))
11283 #else // original
11284         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
11285 #endif
11286           {
11287              bd->want_focus = 0;
11288 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11289              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
11290                 _e_border_check_stack(bd);
11291              else
11292 #endif
11293              e_border_focus_set_with_pointer(bd);
11294           }
11295         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11296           {
11297              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
11298                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
11299                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
11300                    e_border_focused_get())))
11301                {
11302                   e_border_focus_set_with_pointer(bd);
11303                }
11304           }
11305         else
11306           {
11307              /* focus window by default when it is the only one on desk */
11308              E_Border *bd2 = NULL;
11309              Eina_List *l;
11310              EINA_LIST_FOREACH(focus_stack, l, bd2)
11311                {
11312                   if (bd == bd2) continue;
11313                   if ((!bd2->iconic) && (bd2->visible) &&
11314                       ((bd->desk == bd2->desk) || bd2->sticky))
11315                     break;
11316                }
11317
11318              if (!bd2)
11319                {
11320                   e_border_focus_set_with_pointer(bd);
11321                }
11322           }
11323      }
11324
11325    if (bd->need_maximize)
11326      {
11327         E_Maximize max;
11328         max = bd->maximized;
11329         bd->maximized = E_MAXIMIZE_NONE;
11330         e_border_maximize(bd, max);
11331         bd->need_maximize = 0;
11332      }
11333
11334    if (bd->need_fullscreen)
11335      {
11336         e_border_fullscreen(bd, e_config->fullscreen_policy);
11337         bd->need_fullscreen = 0;
11338      }
11339
11340    if (rem_change)
11341      e_remember_update(bd);
11342
11343    if (send_event) // FIXME: send only if a property changed - above need to
11344      { // check on that. for now - always send.
11345         event = E_NEW(E_Event_Border_Property, 1);
11346         event->border = bd;
11347         e_object_ref(E_OBJECT(bd));
11348         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11349      }
11350    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11351 }
11352
11353 static void
11354 _e_border_moveinfo_gather(E_Border   *bd,
11355                           const char *source)
11356 {
11357    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11358    else if (e_util_glob_match(source, "mouse,*,2"))
11359      bd->moveinfo.down.button = 2;
11360    else if (e_util_glob_match(source, "mouse,*,3"))
11361      bd->moveinfo.down.button = 3;
11362    else bd->moveinfo.down.button = 0;
11363    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11364      {
11365         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11366         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11367      }
11368    else
11369      {
11370         bd->moveinfo.down.mx = bd->mouse.current.mx;
11371         bd->moveinfo.down.my = bd->mouse.current.my;
11372      }
11373 }
11374
11375 static void
11376 _e_border_resize_handle(E_Border *bd)
11377 {
11378    int x, y, w, h;
11379    int new_x, new_y, new_w, new_h;
11380    int tw, th;
11381    Eina_List *skiplist = NULL;
11382
11383    x = bd->x;
11384    y = bd->y;
11385    w = bd->w;
11386    h = bd->h;
11387
11388    if ((bd->resize_mode == RESIZE_TR) ||
11389        (bd->resize_mode == RESIZE_R) ||
11390        (bd->resize_mode == RESIZE_BR))
11391      {
11392         if ((bd->moveinfo.down.button >= 1) &&
11393             (bd->moveinfo.down.button <= 3))
11394           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11395             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11396         else
11397           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11398      }
11399    else if ((bd->resize_mode == RESIZE_TL) ||
11400             (bd->resize_mode == RESIZE_L) ||
11401             (bd->resize_mode == RESIZE_BL))
11402      {
11403         if ((bd->moveinfo.down.button >= 1) &&
11404             (bd->moveinfo.down.button <= 3))
11405           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11406             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11407         else
11408           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11409      }
11410
11411    if ((bd->resize_mode == RESIZE_TL) ||
11412        (bd->resize_mode == RESIZE_T) ||
11413        (bd->resize_mode == RESIZE_TR))
11414      {
11415         if ((bd->moveinfo.down.button >= 1) &&
11416             (bd->moveinfo.down.button <= 3))
11417           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11418             (bd->mouse.current.my - bd->moveinfo.down.my);
11419         else
11420           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11421      }
11422    else if ((bd->resize_mode == RESIZE_BL) ||
11423             (bd->resize_mode == RESIZE_B) ||
11424             (bd->resize_mode == RESIZE_BR))
11425      {
11426         if ((bd->moveinfo.down.button >= 1) &&
11427             (bd->moveinfo.down.button <= 3))
11428           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11429             (bd->mouse.current.my - bd->moveinfo.down.my);
11430         else
11431           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11432      }
11433
11434    tw = bd->w;
11435    th = bd->h;
11436
11437    if ((bd->resize_mode == RESIZE_TL) ||
11438        (bd->resize_mode == RESIZE_L) ||
11439        (bd->resize_mode == RESIZE_BL))
11440      x += (tw - w);
11441    if ((bd->resize_mode == RESIZE_TL) ||
11442        (bd->resize_mode == RESIZE_T) ||
11443        (bd->resize_mode == RESIZE_TR))
11444      y += (th - h);
11445
11446    skiplist = eina_list_append(skiplist, bd);
11447    e_resist_container_border_position(bd->zone->container, skiplist,
11448                                       bd->x, bd->y, bd->w, bd->h,
11449                                       x, y, w, h,
11450                                       &new_x, &new_y, &new_w, &new_h);
11451    eina_list_free(skiplist);
11452
11453    w = new_w;
11454    h = new_h;
11455    e_border_resize_limit(bd, &new_w, &new_h);
11456    if ((bd->resize_mode == RESIZE_TL) ||
11457        (bd->resize_mode == RESIZE_L) ||
11458        (bd->resize_mode == RESIZE_BL))
11459      new_x += (w - new_w);
11460    if ((bd->resize_mode == RESIZE_TL) ||
11461        (bd->resize_mode == RESIZE_T) ||
11462        (bd->resize_mode == RESIZE_TR))
11463      new_y += (h - new_h);
11464
11465    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11466 }
11467
11468 static Eina_Bool
11469 _e_border_shade_animator(void *data)
11470 {
11471    E_Border *bd = data;
11472    double dt, val;
11473    double dur = bd->client.h / e_config->border_shade_speed;
11474
11475    dt = ecore_loop_time_get() - bd->shade.start;
11476    val = dt / dur;
11477
11478    if (val < 0.0) val = 0.0;
11479    else if (val > 1.0) val = 1.0;
11480
11481    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11482      {
11483         bd->shade.val =
11484            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
11485         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11486      }
11487    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
11488      {
11489         bd->shade.val =
11490            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
11491         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11492      }
11493    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
11494      {
11495         bd->shade.val =
11496            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
11497         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11498      }
11499    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
11500      {
11501         bd->shade.val =
11502            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11503         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11504      }
11505    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
11506      {
11507         bd->shade.val =
11508            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
11509         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11510      }
11511    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
11512      {
11513         bd->shade.val =
11514            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
11515         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11516      }
11517    else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
11518      {
11519         bd->shade.val =
11520            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.0);
11521         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11522      }
11523    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE)
11524      {
11525         bd->shade.val =
11526            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
11527         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11528      }
11529    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
11530      {
11531         bd->shade.val =
11532            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
11533         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11534      }
11535    else
11536      {
11537         bd->shade.val =
11538            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11539         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11540      }
11541
11542    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
11543    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
11544    else if (bd->shade.val > .999)
11545      bd->shade.val = 1.0;
11546
11547    if (bd->shade.dir == E_DIRECTION_UP)
11548      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11549    else if (bd->shade.dir == E_DIRECTION_DOWN)
11550      {
11551         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11552         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
11553         bd->changes.pos = 1;
11554      }
11555    else if (bd->shade.dir == E_DIRECTION_LEFT)
11556      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11557    else if (bd->shade.dir == E_DIRECTION_RIGHT)
11558      {
11559         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11560         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
11561         bd->changes.pos = 1;
11562      }
11563
11564    if ((bd->shaped) || (bd->client.shaped))
11565      {
11566         bd->need_shape_merge = 1;
11567         bd->need_shape_export = 1;
11568      }
11569    if (bd->shaped_input)
11570      {
11571         bd->need_shape_merge = 1;
11572      }
11573    bd->changes.size = 1;
11574    bd->changed = 1;
11575
11576    /* we're done */
11577    if (val == 1)
11578      {
11579         E_Event_Border_Resize *ev;
11580
11581         bd->shading = 0;
11582         bd->shaded = !(bd->shaded);
11583         bd->changes.size = 1;
11584         bd->changes.shaded = 1;
11585         bd->changes.shading = 1;
11586         bd->changed = 1;
11587         bd->shade.anim = NULL;
11588
11589         if (bd->shaded)
11590           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
11591         else
11592           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
11593         edje_object_message_signal_process(bd->bg_object);
11594         e_border_frame_recalc(bd);
11595
11596         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
11597         ev = E_NEW(E_Event_Border_Resize, 1);
11598         ev->border = bd;
11599         e_object_ref(E_OBJECT(bd));
11600 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
11601         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
11602         return ECORE_CALLBACK_CANCEL;
11603      }
11604    return ECORE_CALLBACK_RENEW;
11605 }
11606
11607 static void
11608 _e_border_event_border_resize_free(void *data __UNUSED__,
11609                                    void      *ev)
11610 {
11611    E_Event_Border_Resize *e;
11612
11613    e = ev;
11614 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
11615    e_object_unref(E_OBJECT(e->border));
11616    E_FREE(e);
11617 }
11618
11619 static void
11620 _e_border_event_border_move_free(void *data __UNUSED__,
11621                                  void      *ev)
11622 {
11623    E_Event_Border_Move *e;
11624
11625    e = ev;
11626 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
11627    e_object_unref(E_OBJECT(e->border));
11628    E_FREE(e);
11629 }
11630
11631 static void
11632 _e_border_event_border_add_free(void *data __UNUSED__,
11633                                 void      *ev)
11634 {
11635    E_Event_Border_Add *e;
11636
11637    e = ev;
11638 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
11639    e_object_unref(E_OBJECT(e->border));
11640    E_FREE(e);
11641 }
11642
11643 static void
11644 _e_border_event_border_remove_free(void *data __UNUSED__,
11645                                    void      *ev)
11646 {
11647    E_Event_Border_Remove *e;
11648
11649    e = ev;
11650 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
11651    e_object_unref(E_OBJECT(e->border));
11652    E_FREE(e);
11653 }
11654
11655 static void
11656 _e_border_event_border_show_free(void *data __UNUSED__,
11657                                  void      *ev)
11658 {
11659    E_Event_Border_Show *e;
11660
11661    e = ev;
11662 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
11663    e_object_unref(E_OBJECT(e->border));
11664    E_FREE(e);
11665 }
11666
11667 static void
11668 _e_border_event_border_hide_free(void *data __UNUSED__,
11669                                  void      *ev)
11670 {
11671    E_Event_Border_Hide *e;
11672
11673    e = ev;
11674 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
11675    e_object_unref(E_OBJECT(e->border));
11676    E_FREE(e);
11677 }
11678
11679 static void
11680 _e_border_event_border_iconify_free(void *data __UNUSED__,
11681                                     void      *ev)
11682 {
11683    E_Event_Border_Iconify *e;
11684
11685    e = ev;
11686 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
11687    e_object_unref(E_OBJECT(e->border));
11688    E_FREE(e);
11689 }
11690
11691 static void
11692 _e_border_event_border_uniconify_free(void *data __UNUSED__,
11693                                       void      *ev)
11694 {
11695    E_Event_Border_Uniconify *e;
11696
11697    e = ev;
11698 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
11699    e_object_unref(E_OBJECT(e->border));
11700    E_FREE(e);
11701 }
11702
11703 static void
11704 _e_border_event_border_stick_free(void *data __UNUSED__,
11705                                   void      *ev)
11706 {
11707    E_Event_Border_Stick *e;
11708
11709    e = ev;
11710 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
11711    e_object_unref(E_OBJECT(e->border));
11712    E_FREE(e);
11713 }
11714
11715 static void
11716 _e_border_event_border_unstick_free(void *data __UNUSED__,
11717                                     void      *ev)
11718 {
11719    E_Event_Border_Unstick *e;
11720
11721    e = ev;
11722 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
11723    e_object_unref(E_OBJECT(e->border));
11724    E_FREE(e);
11725 }
11726
11727 static void
11728 _e_border_event_border_zone_set_free(void *data __UNUSED__,
11729                                      void      *ev)
11730 {
11731    E_Event_Border_Zone_Set *e;
11732
11733    e = ev;
11734 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
11735    e_object_unref(E_OBJECT(e->border));
11736    e_object_unref(E_OBJECT(e->zone));
11737    E_FREE(e);
11738 }
11739
11740 static void
11741 _e_border_event_border_desk_set_free(void *data __UNUSED__,
11742                                      void      *ev)
11743 {
11744    E_Event_Border_Desk_Set *e;
11745
11746    e = ev;
11747 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
11748    e_object_unref(E_OBJECT(e->border));
11749    e_object_unref(E_OBJECT(e->desk));
11750    E_FREE(e);
11751 }
11752
11753 static void
11754 _e_border_event_border_stack_free(void *data __UNUSED__,
11755                                   void      *ev)
11756 {
11757    E_Event_Border_Stack *e;
11758
11759    e = ev;
11760 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
11761    e_object_unref(E_OBJECT(e->border));
11762    if (e->stack)
11763      {
11764 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
11765           e_object_unref(E_OBJECT(e->stack));
11766      }
11767    E_FREE(e);
11768 }
11769
11770 static void
11771 _e_border_event_border_icon_change_free(void *data __UNUSED__,
11772                                         void      *ev)
11773 {
11774    E_Event_Border_Icon_Change *e;
11775
11776    e = ev;
11777 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
11778    e_object_unref(E_OBJECT(e->border));
11779    E_FREE(e);
11780 }
11781
11782 static void
11783 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
11784                                           void      *ev)
11785 {
11786    E_Event_Border_Urgent_Change *e;
11787
11788    e = ev;
11789    e_object_unref(E_OBJECT(e->border));
11790    E_FREE(e);
11791 }
11792
11793 static void
11794 _e_border_event_border_focus_in_free(void *data __UNUSED__,
11795                                      void      *ev)
11796 {
11797    E_Event_Border_Focus_In *e;
11798
11799    e = ev;
11800    e_object_unref(E_OBJECT(e->border));
11801    E_FREE(e);
11802 }
11803
11804 static void
11805 _e_border_event_border_focus_out_free(void *data __UNUSED__,
11806                                       void      *ev)
11807 {
11808    E_Event_Border_Focus_Out *e;
11809
11810    e = ev;
11811    e_object_unref(E_OBJECT(e->border));
11812    E_FREE(e);
11813 }
11814
11815 static void
11816 _e_border_event_border_property_free(void *data __UNUSED__,
11817                                      void      *ev)
11818 {
11819    E_Event_Border_Property *e;
11820
11821    e = ev;
11822    e_object_unref(E_OBJECT(e->border));
11823    E_FREE(e);
11824 }
11825
11826 static void
11827 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
11828                                        void      *ev)
11829 {
11830    E_Event_Border_Fullscreen *e;
11831
11832    e = ev;
11833 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
11834    e_object_unref(E_OBJECT(e->border));
11835    E_FREE(e);
11836 }
11837
11838 static void
11839 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
11840                                          void      *ev)
11841 {
11842    E_Event_Border_Unfullscreen *e;
11843
11844    e = ev;
11845 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
11846    e_object_unref(E_OBJECT(e->border));
11847    E_FREE(e);
11848 }
11849
11850 #ifdef _F_ZONE_WINDOW_ROTATION_
11851 static void
11852 _e_border_event_border_rotation_change_begin_free(void *data __UNUSED__,
11853                                                   void      *ev)
11854 {
11855    E_Event_Border_Rotation_Change_Begin *e;
11856    e = ev;
11857    e_object_unref(E_OBJECT(e->border));
11858    E_FREE(e);
11859 }
11860
11861 static void
11862 _e_border_event_border_rotation_change_cancel_free(void *data __UNUSED__,
11863                                                    void      *ev)
11864 {
11865    E_Event_Border_Rotation_Change_Cancel *e;
11866    e = ev;
11867    e_object_unref(E_OBJECT(e->border));
11868    E_FREE(e);
11869 }
11870
11871 static void
11872 _e_border_event_border_rotation_change_end_free(void *data __UNUSED__,
11873                                                 void      *ev)
11874 {
11875    E_Event_Border_Rotation_Change_End *e;
11876    e = ev;
11877    e_object_unref(E_OBJECT(e->border));
11878    E_FREE(e);
11879 }
11880
11881 static void
11882 _e_border_event_border_rotation_change_begin_send(E_Border *bd)
11883 {
11884    E_Event_Border_Rotation_Change_Begin *ev = NULL;
11885    ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
11886    if (ev)
11887      {
11888         ev->border = bd;
11889         e_object_ref(E_OBJECT(bd));
11890         ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_BEGIN,
11891                         ev,
11892                         _e_border_event_border_rotation_change_begin_free,
11893                         NULL);
11894      }
11895 }
11896 #endif
11897
11898 static void
11899 _e_border_zone_update(E_Border *bd)
11900 {
11901    E_Container *con;
11902    Eina_List *l;
11903    E_Zone *zone;
11904
11905    /* still within old zone - leave it there */
11906    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
11907                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
11908 #if _F_BORDER_CLIP_TO_ZONE_
11909      {
11910         _e_border_shape_input_clip_to_zone(bd);
11911         return;
11912      }
11913 #else
11914      return;
11915 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
11916    /* find a new zone */
11917    con = bd->zone->container;
11918    EINA_LIST_FOREACH(con->zones, l, zone)
11919      {
11920         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
11921                          zone->x, zone->y, zone->w, zone->h))
11922           {
11923              e_border_zone_set(bd, zone);
11924 #if _F_BORDER_CLIP_TO_ZONE_
11925              _e_border_shape_input_clip_to_zone(bd);
11926 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
11927              return;
11928           }
11929      }
11930 }
11931
11932 static int
11933 _e_border_resize_begin(E_Border *bd)
11934 {
11935    if (!bd->lock_user_stacking)
11936      {
11937         if (e_config->border_raise_on_mouse_action)
11938           e_border_raise(bd);
11939      }
11940    if ((bd->shaded) || (bd->shading) ||
11941        (bd->fullscreen) || (bd->lock_user_size))
11942      return 0;
11943
11944    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
11945      {
11946         grabbed = 0;
11947         return 0;
11948      }
11949
11950    if (bd->client.netwm.sync.request)
11951      {
11952         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
11953         bd->client.netwm.sync.serial = 1;
11954         bd->client.netwm.sync.wait = 0;
11955         bd->client.netwm.sync.send_time = ecore_loop_time_get();
11956      }
11957
11958    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
11959
11960    bdresize = bd;
11961    return 1;
11962 }
11963
11964 static int
11965 _e_border_resize_end(E_Border *bd)
11966 {
11967    if (grabbed)
11968      {
11969         e_grabinput_release(bd->win, bd->win);
11970         grabbed = 0;
11971      }
11972    if (bd->client.netwm.sync.alarm)
11973      {
11974         E_Border_Pending_Move_Resize *pnd;
11975
11976         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
11977         bd->client.netwm.sync.alarm = 0;
11978         /* resize to last geometry if sync alarm for it was not yet handled */
11979         if (bd->pending_move_resize)
11980           {
11981              bd->changed = 1;
11982              bd->changes.pos = 1;
11983              bd->changes.size = 1;
11984              _e_border_client_move_resize_send(bd);
11985           }
11986
11987         EINA_LIST_FREE(bd->pending_move_resize, pnd)
11988           E_FREE(pnd);
11989      }
11990
11991    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
11992
11993    bdresize = NULL;
11994
11995    /* If this border was maximized, we need to unset Maximized state or
11996     * on restart, E still thinks it's maximized */
11997    if (bd->maximized != E_MAXIMIZE_NONE)
11998      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
11999                                   bd->maximized & E_MAXIMIZE_NONE);
12000    return 1;
12001 }
12002
12003 static void
12004 _e_border_resize_update(E_Border *bd)
12005 {
12006    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
12007 }
12008
12009 static int
12010 _e_border_move_begin(E_Border *bd)
12011 {
12012    if (!bd->lock_user_stacking)
12013      {
12014         if (e_config->border_raise_on_mouse_action)
12015           e_border_raise(bd);
12016      }
12017    if ((bd->fullscreen) || (bd->lock_user_location))
12018      return 0;
12019
12020    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
12021      {
12022         grabbed = 0;
12023         return 0;
12024      }
12025 #if 0
12026    if (bd->client.netwm.sync.request)
12027      {
12028         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12029         bd->client.netwm.sync.serial = 0;
12030         bd->client.netwm.sync.wait = 0;
12031         bd->client.netwm.sync.time = ecore_loop_time_get();
12032      }
12033 #endif
12034    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
12035
12036    bdmove = bd;
12037    return 1;
12038 }
12039
12040 static int
12041 _e_border_move_end(E_Border *bd)
12042 {
12043    if (grabbed)
12044      {
12045         e_grabinput_release(bd->win, bd->win);
12046         grabbed = 0;
12047      }
12048 #if 0
12049    if (bd->client.netwm.sync.alarm)
12050      {
12051         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12052         bd->client.netwm.sync.alarm = 0;
12053      }
12054 #endif
12055    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
12056
12057    bdmove = NULL;
12058    return 1;
12059 }
12060
12061 static void
12062 _e_border_move_update(E_Border *bd)
12063 {
12064    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
12065 }
12066
12067 static Eina_Bool
12068 _e_border_cb_ping_poller(void *data)
12069 {
12070    E_Border *bd;
12071
12072    bd = data;
12073    if (bd->ping_ok)
12074      {
12075         if (bd->hung)
12076           {
12077              bd->hung = 0;
12078              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
12079              if (bd->kill_timer)
12080                {
12081                   ecore_timer_del(bd->kill_timer);
12082                   bd->kill_timer = NULL;
12083                }
12084           }
12085      }
12086    else
12087      {
12088         /* if time between last ping and now is greater
12089          * than half the ping interval... */
12090         if ((ecore_loop_time_get() - bd->ping) >
12091             ((e_config->ping_clients_interval *
12092               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
12093           {
12094              if (!bd->hung)
12095                {
12096                   bd->hung = 1;
12097                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
12098                   /* FIXME: if below dialog is up - hide it now */
12099                }
12100              if (bd->delete_requested)
12101                {
12102                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
12103                   e_border_act_kill_begin(bd);
12104                }
12105           }
12106      }
12107    bd->ping_poller = NULL;
12108    e_border_ping(bd);
12109    return ECORE_CALLBACK_CANCEL;
12110 }
12111
12112 static Eina_Bool
12113 _e_border_cb_kill_timer(void *data)
12114 {
12115    E_Border *bd;
12116
12117    bd = data;
12118 // dont wait until it's hung -
12119 //   if (bd->hung)
12120 //     {
12121         if (bd->client.netwm.pid > 1)
12122           kill(bd->client.netwm.pid, SIGKILL);
12123 //     }
12124    bd->kill_timer = NULL;
12125    return ECORE_CALLBACK_CANCEL;
12126 }
12127
12128 static void
12129 _e_border_pointer_resize_begin(E_Border *bd)
12130 {
12131    switch (bd->resize_mode)
12132      {
12133       case RESIZE_TL:
12134         e_pointer_type_push(bd->pointer, bd, "resize_tl");
12135         break;
12136
12137       case RESIZE_T:
12138         e_pointer_type_push(bd->pointer, bd, "resize_t");
12139         break;
12140
12141       case RESIZE_TR:
12142         e_pointer_type_push(bd->pointer, bd, "resize_tr");
12143         break;
12144
12145       case RESIZE_R:
12146         e_pointer_type_push(bd->pointer, bd, "resize_r");
12147         break;
12148
12149       case RESIZE_BR:
12150         e_pointer_type_push(bd->pointer, bd, "resize_br");
12151         break;
12152
12153       case RESIZE_B:
12154         e_pointer_type_push(bd->pointer, bd, "resize_b");
12155         break;
12156
12157       case RESIZE_BL:
12158         e_pointer_type_push(bd->pointer, bd, "resize_bl");
12159         break;
12160
12161       case RESIZE_L:
12162         e_pointer_type_push(bd->pointer, bd, "resize_l");
12163         break;
12164      }
12165 }
12166
12167 static void
12168 _e_border_pointer_resize_end(E_Border *bd)
12169 {
12170    switch (bd->resize_mode)
12171      {
12172       case RESIZE_TL:
12173         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
12174         break;
12175
12176       case RESIZE_T:
12177         e_pointer_type_pop(bd->pointer, bd, "resize_t");
12178         break;
12179
12180       case RESIZE_TR:
12181         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
12182         break;
12183
12184       case RESIZE_R:
12185         e_pointer_type_pop(bd->pointer, bd, "resize_r");
12186         break;
12187
12188       case RESIZE_BR:
12189         e_pointer_type_pop(bd->pointer, bd, "resize_br");
12190         break;
12191
12192       case RESIZE_B:
12193         e_pointer_type_pop(bd->pointer, bd, "resize_b");
12194         break;
12195
12196       case RESIZE_BL:
12197         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
12198         break;
12199
12200       case RESIZE_L:
12201         e_pointer_type_pop(bd->pointer, bd, "resize_l");
12202         break;
12203      }
12204 }
12205
12206 static void
12207 _e_border_pointer_move_begin(E_Border *bd)
12208 {
12209    e_pointer_type_push(bd->pointer, bd, "move");
12210 }
12211
12212 static void
12213 _e_border_pointer_move_end(E_Border *bd)
12214 {
12215    e_pointer_type_pop(bd->pointer, bd, "move");
12216 }
12217
12218 static Eina_List *_e_border_hooks = NULL;
12219 static int _e_border_hooks_delete = 0;
12220 static int _e_border_hooks_walking = 0;
12221
12222 static void
12223 _e_border_hooks_clean(void)
12224 {
12225    Eina_List *l, *ln;
12226    E_Border_Hook *bh;
12227
12228    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
12229      {
12230         if (bh->delete_me)
12231           {
12232              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
12233              free(bh);
12234           }
12235      }
12236 }
12237
12238 static void
12239 _e_border_hook_call(E_Border_Hook_Point hookpoint,
12240                     void               *bd)
12241 {
12242    Eina_List *l;
12243    E_Border_Hook *bh;
12244
12245    _e_border_hooks_walking++;
12246    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
12247      {
12248         if (bh->delete_me) continue;
12249         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
12250      }
12251    _e_border_hooks_walking--;
12252    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
12253      _e_border_hooks_clean();
12254 }
12255
12256 EAPI E_Border_Hook *
12257 e_border_hook_add(E_Border_Hook_Point               hookpoint,
12258                   void                              (*func)(void *data,
12259                                               void *bd),
12260                   void                             *data)
12261 {
12262    E_Border_Hook *bh;
12263
12264    bh = E_NEW(E_Border_Hook, 1);
12265    if (!bh) return NULL;
12266    bh->hookpoint = hookpoint;
12267    bh->func = func;
12268    bh->data = data;
12269    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
12270    return bh;
12271 }
12272
12273 EAPI void
12274 e_border_hook_del(E_Border_Hook *bh)
12275 {
12276    bh->delete_me = 1;
12277    if (_e_border_hooks_walking == 0)
12278      {
12279         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
12280         free(bh);
12281      }
12282    else
12283      _e_border_hooks_delete++;
12284 }
12285
12286 EAPI void
12287 e_border_focus_track_freeze(void)
12288 {
12289    focus_track_frozen++;
12290 }
12291
12292 EAPI void
12293 e_border_focus_track_thaw(void)
12294 {
12295    focus_track_frozen--;
12296 }
12297
12298 EAPI E_Border *
12299 e_border_under_pointer_get(E_Desk   *desk,
12300                            E_Border *exclude)
12301 {
12302    E_Border *bd = NULL, *cbd;
12303    Eina_List *l;
12304    int x, y;
12305
12306    /* We need to ensure that we can get the container window for the
12307     * zone of either the given desk or the desk of the excluded
12308     * window, so return if neither is given */
12309    if (desk)
12310      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
12311    else if (exclude)
12312      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
12313    else
12314      return NULL;
12315
12316    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
12317      {
12318         if (!cbd) continue;
12319         /* If a border was specified which should be excluded from the list
12320          * (because it will be closed shortly for example), skip */
12321         if ((exclude) && (cbd == exclude)) continue;
12322         if ((desk) && (cbd->desk != desk)) continue;
12323         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
12324           continue;
12325         /* If the layer is higher, the position of the window is higher
12326          * (always on top vs always below) */
12327         if (!bd || (cbd->layer > bd->layer))
12328           {
12329              bd = cbd;
12330              break;
12331           }
12332      }
12333    return bd;
12334 }
12335
12336 static Eina_Bool
12337 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
12338 {
12339    if (warp_to)
12340      {
12341         int x, y;
12342         double spd;
12343
12344         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
12345         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
12346             (y - warp_y) > 5 || (y - warp_y) < -5)
12347           {
12348              /* User moved the mouse, so stop warping */
12349              warp_to = 0;
12350              goto cleanup;
12351           }
12352
12353         /* We just use the same warp speed as configured
12354          * for the windowlist */
12355         spd = e_config->winlist_warp_speed;
12356         x = warp_x;
12357         y = warp_y;
12358         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12359         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12360         if (warp_x == x && warp_y == y)
12361           {
12362              warp_x = warp_to_x;
12363              warp_y = warp_to_y;
12364              warp_to = 0;
12365              goto cleanup;
12366           }
12367         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12368         return ECORE_CALLBACK_RENEW;
12369      }
12370  cleanup:
12371    ecore_timer_del(warp_timer);
12372    warp_timer = NULL;
12373    return ECORE_CALLBACK_CANCEL;
12374 }
12375
12376 EAPI int
12377 e_border_pointer_warp_to_center(E_Border *bd)
12378 {
12379    int x, y;
12380
12381    /* Do not slide pointer when disabled (probably breaks focus
12382     * on sloppy/mouse focus but requested by users). */
12383    if (!e_config->pointer_slide) return 0;
12384    /* Only warp the pointer if it is not already in the area of
12385     * the given border */
12386    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12387    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12388        (y >= bd->y) && (y <= (bd->y + bd->h)))
12389      return 0;
12390
12391    warp_to_x = bd->x + (bd->w / 2);
12392    if (warp_to_x < (bd->zone->x + 1))
12393      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12394    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12395      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12396
12397    warp_to_y = bd->y + (bd->h / 2);
12398    if (warp_to_y < (bd->zone->y + 1))
12399      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12400    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12401      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12402
12403    warp_to = 1;
12404    warp_to_win = bd->zone->container->win;
12405    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12406    if (!warp_timer)
12407      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12408    return 1;
12409 }
12410
12411 EAPI void
12412 e_border_comp_hidden_set(E_Border *bd,
12413                          Eina_Bool hidden)
12414 {
12415    E_Border *tmp;
12416    Eina_List *l;
12417
12418    E_OBJECT_CHECK(bd);
12419    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12420
12421    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12422      {
12423        if (hidden)
12424          ecore_x_window_hide(tmp->win);
12425        else
12426          ecore_x_window_show(tmp->win);
12427      }
12428
12429    if (bd->comp_hidden == hidden) return;
12430
12431    bd->comp_hidden = hidden;
12432
12433    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12434      {
12435         ecore_x_composite_window_events_disable(bd->win);
12436         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12437      }
12438    else
12439      {
12440         _e_border_shape_input_rectangle_set(bd);
12441         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12442      }
12443 }
12444
12445 EAPI void
12446 e_border_tmp_input_hidden_push(E_Border *bd)
12447 {
12448    E_Border *tmp;
12449    Eina_List *l;
12450
12451    E_OBJECT_CHECK(bd);
12452    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12453
12454    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12455      e_border_tmp_input_hidden_push(tmp);
12456
12457    bd->tmp_input_hidden++;
12458    if (bd->tmp_input_hidden != 1) return;
12459
12460    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12461      {
12462         ecore_x_composite_window_events_disable(bd->win);
12463         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12464      }
12465    else
12466      {
12467         _e_border_shape_input_rectangle_set(bd);
12468         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12469      }
12470 }
12471
12472 EAPI void
12473 e_border_tmp_input_hidden_pop(E_Border *bd)
12474 {
12475    E_Border *tmp;
12476    Eina_List *l;
12477
12478    E_OBJECT_CHECK(bd);
12479    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12480
12481    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12482      e_border_tmp_input_hidden_pop(tmp);
12483
12484    bd->tmp_input_hidden--;
12485    if (bd->tmp_input_hidden != 0) return;
12486
12487    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12488      {
12489         ecore_x_composite_window_events_disable(bd->win);
12490         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12491      }
12492    else
12493      {
12494         _e_border_shape_input_rectangle_set(bd);
12495         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12496      }
12497 }
12498
12499 EAPI void
12500 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
12501 {
12502    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
12503        ((bd->parent) &&
12504         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
12505          ((bd->parent->focused) &&
12506           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
12507        (just_do_it))
12508      {
12509         if (bd->iconic)
12510           {
12511              if (e_config->clientlist_warp_to_iconified_desktop == 1)
12512                e_desk_show(bd->desk);
12513              
12514              if (!bd->lock_user_iconify)
12515                e_border_uniconify(bd);
12516           }
12517         if ((!bd->iconic) && (!bd->sticky))
12518           e_desk_show(bd->desk);
12519         if (!bd->lock_user_stacking) e_border_raise(bd);
12520         if (!bd->lock_focus_out)
12521           {
12522              /* XXX ooffice does send this request for
12523               config dialogs when the main window gets focus.
12524               causing the pointer to jump back and forth.  */
12525              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
12526                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
12527                ecore_x_pointer_warp(bd->zone->container->win,
12528                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
12529              e_border_focus_set(bd, 1, 1);
12530           }
12531      }
12532 }
12533 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/