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