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