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