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