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