5c567876f89a89c62c4137f7055c17fdd7f42a5f
[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)
5768      {
5769         if (ecore_x_window_visible_get(e->win))
5770           {
5771              ELB(ELBT_BD, "FORCE UNMAP client window", e->win);
5772              ecore_x_window_hide(e->win);
5773           }
5774         return ECORE_CALLBACK_PASS_ON;
5775      }
5776
5777 //   printf("  bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap);
5778    if (bd->ignore_first_unmap > 0)
5779      {
5780         bd->ignore_first_unmap--;
5781         return ECORE_CALLBACK_PASS_ON;
5782      }
5783    /* Don't delete hidden or iconified windows */
5784 #ifdef _F_USE_EXTENDED_ICONIFY_
5785    if (bd->await_hide_event > 0)
5786 #else
5787    if ((bd->iconic) || (bd->await_hide_event > 0))
5788 #endif
5789      {
5790 //        printf("  Don't delete hidden or iconified windows\n");
5791 //        printf("  bd->iconic = %i, bd->visible = %i, bd->new_client = %i, bd->await_hide_event = %i\n",
5792 //               bd->iconic, bd->visible, bd->new_client, bd->await_hide_event);
5793         if (bd->await_hide_event > 0)
5794           {
5795              bd->await_hide_event--;
5796           }
5797         else
5798           {
5799 //             printf("  hide really\n");
5800              /* Only hide the border if it is visible */
5801              if (bd->visible) e_border_hide(bd, 1);
5802           }
5803      }
5804    else
5805      {
5806 //             printf("  hide2\n");
5807 #ifdef _F_USE_EXTENDED_ICONIFY_
5808         if (bd->iconic)
5809           {
5810              bd->iconic = 0;
5811              bd->visible = 1;
5812           }
5813 #endif
5814         e_border_hide(bd, 0);
5815         e_object_del(E_OBJECT(bd));
5816      }
5817    return ECORE_CALLBACK_PASS_ON;
5818 }
5819
5820 static Eina_Bool
5821 _e_border_cb_window_reparent(void *data  __UNUSED__,
5822                              int ev_type __UNUSED__,
5823                              void *ev    __UNUSED__)
5824 {
5825 #if 0
5826    E_Border *bd;
5827    Ecore_X_Event_Window_Reparent *e;
5828
5829    e = ev;
5830    bd = e_border_find_by_client_window(e->win);
5831    if (!bd) return 1;
5832    if (e->parent == bd->client.shell_win) return 1;
5833    if (ecore_x_window_parent_get(e->win) == bd->client.shell_win)
5834      {
5835         return 1;
5836      }
5837    e_border_hide(bd, 0);
5838    e_object_del(E_OBJECT(bd));
5839 #endif
5840    return ECORE_CALLBACK_PASS_ON;
5841 }
5842
5843 static Eina_Bool
5844 _e_border_cb_window_configure_request(void *data  __UNUSED__,
5845                                       int ev_type __UNUSED__,
5846                                       void       *ev)
5847 {
5848    E_Border *bd;
5849    Ecore_X_Event_Window_Configure_Request *e;
5850
5851    e = ev;
5852    bd = e_border_find_by_client_window(e->win);
5853    if (!bd)
5854      {
5855         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
5856         if (!e_util_container_window_find(e->win))
5857           ecore_x_window_configure(e->win, e->value_mask,
5858                                    e->x, e->y, e->w, e->h, e->border,
5859                                    e->abovewin, e->detail);
5860         return ECORE_CALLBACK_PASS_ON;
5861      }
5862
5863    if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
5864        (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
5865      {
5866         int x, y;
5867
5868         x = bd->x;
5869         y = bd->y;
5870         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
5871           x = e->x;
5872         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
5873           y = e->y;
5874         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
5875             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
5876           {
5877              int w, h;
5878
5879              h = bd->h;
5880              w = bd->w;
5881              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
5882                w = e->w + bd->client_inset.l + bd->client_inset.r;
5883              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
5884                h = e->h + bd->client_inset.t + bd->client_inset.b;
5885              if ((!bd->lock_client_location) && (!bd->lock_client_size))
5886                {
5887                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
5888                     {
5889                        bd->saved.x = x - bd->zone->x;
5890                        bd->saved.y = y - bd->zone->y;
5891                        bd->saved.w = w;
5892                        bd->saved.h = h;
5893                     }
5894                   else
5895                     e_border_move_resize(bd, x, y, w, h);
5896                }
5897              else if (!bd->lock_client_location)
5898                {
5899                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
5900                     {
5901                        bd->saved.x = x - bd->zone->x;
5902                        bd->saved.y = y - bd->zone->y;
5903                     }
5904                   else
5905                     e_border_move(bd, x, y);
5906                }
5907              else if (!bd->lock_client_size)
5908                {
5909                   if ((bd->shaded) || (bd->shading))
5910                     {
5911                        int pw, ph;
5912
5913                        pw = bd->client.w;
5914                        ph = bd->client.h;
5915                        if ((bd->shade.dir == E_DIRECTION_UP) ||
5916                            (bd->shade.dir == E_DIRECTION_DOWN))
5917                          {
5918                             e_border_resize(bd, w, bd->h);
5919                             bd->client.h = ph;
5920                          }
5921                        else
5922                          {
5923                             e_border_resize(bd, bd->w, h);
5924                             bd->client.w = pw;
5925                          }
5926                     }
5927                   else
5928                     {
5929                        if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
5930                          {
5931                             bd->saved.w = w;
5932                             bd->saved.h = h;
5933                          }
5934                        else
5935                          e_border_resize(bd, w, h);
5936                     }
5937                }
5938           }
5939         else
5940           {
5941              if (!bd->lock_client_location)
5942                {
5943                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
5944                     {
5945                        bd->saved.x = x - bd->zone->x;
5946                        bd->saved.y = y - bd->zone->y;
5947                     }
5948                   else
5949                     e_border_move(bd, x, y);
5950                }
5951           }
5952      }
5953    else if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
5954             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
5955      {
5956         int w, h;
5957
5958         h = bd->h;
5959         w = bd->w;
5960         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
5961           w = e->w + bd->client_inset.l + bd->client_inset.r;
5962         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
5963           h = e->h + bd->client_inset.t + bd->client_inset.b;
5964 #ifdef _F_ZONE_WINDOW_ROTATION_
5965         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
5966 #endif
5967         if (!bd->lock_client_size)
5968           {
5969              if ((bd->shaded) || (bd->shading))
5970                {
5971                   int pw, ph;
5972
5973                   pw = bd->client.w;
5974                   ph = bd->client.h;
5975                   if ((bd->shade.dir == E_DIRECTION_UP) ||
5976                       (bd->shade.dir == E_DIRECTION_DOWN))
5977                     {
5978                        e_border_resize(bd, w, bd->h);
5979                        bd->client.h = ph;
5980                     }
5981                   else
5982                     {
5983                        e_border_resize(bd, bd->w, h);
5984                        bd->client.w = pw;
5985                     }
5986                }
5987              else
5988                {
5989                   if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE)
5990                     {
5991                        int zx, zy, zw, zh;
5992                        int rx = bd->x;
5993                        int ry = bd->y;
5994                        zx = zy = zw = zh = 0;
5995
5996      /*
5997       * This code does resize and move a window on a
5998       * X configure request into an useful geometry.
5999       * This is really useful for size jumping file dialogs.
6000       */
6001
6002                        if (bd->zone)
6003                          {
6004                             e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
6005
6006                             if (e_config->geometry_auto_resize_limit == 1)
6007                               {
6008                                  if (w > zw)
6009                                    w = zw;
6010
6011                                  if (h > zh)
6012                                    h = zh;
6013                               }
6014                          }
6015                        e_border_resize(bd, w, h);
6016
6017                        if (e_config->geometry_auto_move == 1)
6018                          {
6019                              /* z{x,y,w,h} are only set here; FIXME! */
6020                              if (bd->zone)
6021                                {
6022                                   // move window horizontal if resize to not useful geometry
6023                                   if (bd->x + bd->w > zx + zw)
6024                                     rx = zx + zw - bd->w;
6025                                   else if (bd->x < zx)
6026                                     rx = zx;
6027
6028                                   // move window vertical if resize to not useful geometry
6029                                   if (bd->y + bd->h > zy + zh)
6030                                     ry = zy + zh - bd->h;
6031                                   else if (bd->y < zy)
6032                                     ry = zy;
6033                                }
6034                              e_border_move(bd, rx, ry);
6035                          }
6036                     }
6037                }
6038           }
6039      }
6040    if (!bd->lock_client_stacking)
6041      {
6042         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
6043             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
6044           {
6045              E_Border *obd;
6046
6047              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6048                {
6049                   obd = e_border_find_by_client_window(e->abovewin);
6050                   if (obd)
6051                     {
6052                        e_border_stack_above(bd, obd);
6053                     }
6054                   else
6055                     {
6056                        ecore_x_window_configure(bd->win,
6057                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6058                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6059                                                 0, 0, 0, 0, 0,
6060                                                 e->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
6061                        /* FIXME: need to rebuiuld border list from current stacking */
6062                     }
6063                }
6064              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6065                {
6066                   obd = e_border_find_by_client_window(e->abovewin);
6067                   if (obd)
6068                     {
6069                        e_border_stack_below(bd, obd);
6070                     }
6071                   else
6072                     {
6073                        ecore_x_window_configure(bd->win,
6074                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6075                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6076                                                 0, 0, 0, 0, 0,
6077                                                 e->abovewin, ECORE_X_WINDOW_STACK_BELOW);
6078                        /* FIXME: need to rebuiuld border list from current stacking */
6079                     }
6080                }
6081              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6082                {
6083      /* FIXME: do */
6084                }
6085              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6086                {
6087      /* FIXME: do */
6088                }
6089              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6090                {
6091      /* FIXME: do */
6092                }
6093           }
6094         else if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
6095           {
6096              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6097                {
6098                   e_border_raise(bd);
6099                }
6100              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6101                {
6102                   e_border_lower(bd);
6103                }
6104              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6105                {
6106      /* FIXME: do */
6107                }
6108              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6109                {
6110      /* FIXME: do */
6111                }
6112              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6113                {
6114      /* FIXME: do */
6115                }
6116           }
6117      }
6118
6119    /* FIXME: need to send synthetic stacking event too as well as move/resize */
6120    _e_border_client_move_resize_send(bd);
6121    return ECORE_CALLBACK_PASS_ON;
6122 }
6123
6124 static Eina_Bool
6125 _e_border_cb_window_resize_request(void *data  __UNUSED__,
6126                                    int ev_type __UNUSED__,
6127                                    void       *ev)
6128 {
6129    E_Border *bd;
6130    Ecore_X_Event_Window_Resize_Request *e;
6131
6132    e = ev;
6133    bd = e_border_find_by_client_window(e->win);
6134    if (!bd)
6135      {
6136         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6137         ecore_x_window_resize(e->win, e->w, e->h);
6138         return ECORE_CALLBACK_PASS_ON;
6139      }
6140    {
6141       int w, h;
6142
6143       w = e->w + bd->client_inset.l + bd->client_inset.r;
6144       h = e->h + bd->client_inset.t + bd->client_inset.b;
6145       if ((bd->shaded) || (bd->shading))
6146         {
6147            int pw, ph;
6148
6149            pw = bd->client.w;
6150            ph = bd->client.h;
6151            if ((bd->shade.dir == E_DIRECTION_UP) ||
6152                (bd->shade.dir == E_DIRECTION_DOWN))
6153              {
6154                 e_border_resize(bd, w, bd->h);
6155                 bd->client.h = ph;
6156              }
6157            else
6158              {
6159                 e_border_resize(bd, bd->w, h);
6160                 bd->client.w = pw;
6161              }
6162         }
6163       else
6164         e_border_resize(bd, w, h);
6165    }
6166
6167    _e_border_client_move_resize_send(bd);
6168    return ECORE_CALLBACK_PASS_ON;
6169 }
6170
6171 static Eina_Bool
6172 _e_border_cb_window_gravity(void *data  __UNUSED__,
6173                             int ev_type __UNUSED__,
6174                             void *ev    __UNUSED__)
6175 {
6176 //   E_Border *bd;
6177 //   Ecore_X_Event_Window_Gravity *e;
6178
6179 //   e = ev;
6180 //   bd = e_border_find_by_client_window(e->win);
6181 //   if (!bd) return 1;
6182              return 1;
6183 }
6184
6185 static Eina_Bool
6186 _e_border_cb_window_stack_request(void *data  __UNUSED__,
6187                                   int ev_type __UNUSED__,
6188                                   void       *ev)
6189 {
6190    E_Border *bd;
6191    Ecore_X_Event_Window_Stack_Request *e;
6192
6193    e = ev;
6194    bd = e_border_find_by_client_window(e->win);
6195    if (!bd)
6196      {
6197         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6198         if (!e_util_container_window_find(e->win))
6199           {
6200              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6201                ecore_x_window_raise(e->win);
6202              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6203                ecore_x_window_lower(e->win);
6204           }
6205         return ECORE_CALLBACK_PASS_ON;
6206      }
6207    if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6208      e_border_raise(bd);
6209    else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6210      e_border_lower(bd);
6211    return ECORE_CALLBACK_PASS_ON;
6212 }
6213
6214 static Eina_Bool
6215 _e_border_cb_window_property(void *data  __UNUSED__,
6216                              int ev_type __UNUSED__,
6217                              void       *ev)
6218 {
6219    E_Border *bd;
6220    Ecore_X_Event_Window_Property *e;
6221
6222    e = ev;
6223    bd = e_border_find_by_client_window(e->win);
6224    if (!bd) return ECORE_CALLBACK_PASS_ON;
6225    if (e->atom == ECORE_X_ATOM_WM_NAME)
6226      {
6227         if ((!bd->client.netwm.name) &&
6228             (!bd->client.netwm.fetch.name))
6229           {
6230              bd->client.icccm.fetch.title = 1;
6231              bd->changed = 1;
6232           }
6233      }
6234    else if (e->atom == ECORE_X_ATOM_NET_WM_NAME)
6235      {
6236         bd->client.netwm.fetch.name = 1;
6237         bd->changed = 1;
6238      }
6239    else if (e->atom == ECORE_X_ATOM_WM_CLASS)
6240      {
6241         bd->client.icccm.fetch.name_class = 1;
6242         bd->changed = 1;
6243      }
6244    else if (e->atom == ECORE_X_ATOM_WM_ICON_NAME)
6245      {
6246         if ((!bd->client.netwm.icon_name) &&
6247             (!bd->client.netwm.fetch.icon_name))
6248           {
6249              bd->client.icccm.fetch.icon_name = 1;
6250              bd->changed = 1;
6251           }
6252      }
6253    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
6254      {
6255         bd->client.netwm.fetch.icon_name = 1;
6256         bd->changed = 1;
6257      }
6258    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
6259      {
6260         bd->client.icccm.fetch.machine = 1;
6261         bd->changed = 1;
6262      }
6263    else if (e->atom == ECORE_X_ATOM_WM_PROTOCOLS)
6264      {
6265         bd->client.icccm.fetch.protocol = 1;
6266         bd->changed = 1;
6267      }
6268    else if (e->atom == ECORE_X_ATOM_WM_HINTS)
6269      {
6270         bd->client.icccm.fetch.hints = 1;
6271         bd->changed = 1;
6272      }
6273    else if (e->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
6274      {
6275         bd->client.icccm.fetch.size_pos_hints = 1;
6276         bd->changed = 1;
6277      }
6278    else if (e->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
6279      {
6280         /*
6281            if ((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN) &&
6282             (!bd->client.netwm.fetch.type))
6283            {
6284          */
6285           bd->client.mwm.fetch.hints = 1;
6286           bd->changed = 1;
6287           /*
6288              }
6289            */
6290      }
6291    else if (e->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
6292      {
6293         bd->client.icccm.fetch.transient_for = 1;
6294         bd->changed = 1;
6295      }
6296    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
6297      {
6298         bd->client.icccm.fetch.client_leader = 1;
6299         bd->changed = 1;
6300      }
6301    else if (e->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
6302      {
6303         bd->client.icccm.fetch.window_role = 1;
6304         bd->changed = 1;
6305      }
6306    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON)
6307      {
6308         bd->client.netwm.fetch.icon = 1;
6309         bd->changed = 1;
6310      }
6311    else if (e->atom == ATM__QTOPIA_SOFT_MENU)
6312      {
6313         bd->client.qtopia.fetch.soft_menu = 1;
6314         bd->changed = 1;
6315      }
6316    else if (e->atom == ATM__QTOPIA_SOFT_MENUS)
6317      {
6318         bd->client.qtopia.fetch.soft_menus = 1;
6319         bd->changed = 1;
6320      }
6321    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
6322      {
6323         bd->client.vkbd.fetch.state = 1;
6324         bd->changed = 1;
6325      }
6326    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
6327      {
6328         bd->client.vkbd.fetch.vkbd = 1;
6329         bd->changed = 1;
6330      }
6331    else if (e->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
6332      {
6333         bd->client.illume.conformant.fetch.conformant = 1;
6334         bd->changed = 1;
6335      }
6336    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
6337      {
6338         bd->client.illume.quickpanel.fetch.state = 1;
6339         bd->changed = 1;
6340      }
6341    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
6342      {
6343         bd->client.illume.quickpanel.fetch.quickpanel = 1;
6344         bd->changed = 1;
6345      }
6346    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
6347      {
6348         bd->client.illume.quickpanel.fetch.priority.major = 1;
6349         bd->changed = 1;
6350      }
6351    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
6352      {
6353         bd->client.illume.quickpanel.fetch.priority.minor = 1;
6354         bd->changed = 1;
6355      }
6356    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
6357      {
6358         bd->client.illume.quickpanel.fetch.zone = 1;
6359         bd->changed = 1;
6360      }
6361    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
6362      {
6363         bd->client.illume.drag.fetch.locked = 1;
6364         bd->changed = 1;
6365      }
6366    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
6367      {
6368         bd->client.illume.drag.fetch.drag = 1;
6369         bd->changed = 1;
6370      }
6371    else if (e->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
6372      {
6373         bd->client.illume.win_state.fetch.state = 1;
6374         bd->changed = 1;
6375      }
6376    /*
6377       else if (e->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
6378       {
6379         bd->client.netwm.fetch.user_time = 1;
6380         bd->changed = 1;
6381       }
6382       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT)
6383       {
6384         bd->client.netwm.fetch.strut = 1;
6385         bd->changed = 1;
6386       }
6387       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
6388       {
6389         bd->client.netwm.fetch.strut = 1;
6390         bd->changed = 1;
6391       }
6392     */
6393    else if (e->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
6394      {
6395         //printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
6396      }
6397    else if (e->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
6398      {
6399         bd->client.e.fetch.video_position = 1;
6400         bd->changed = 1;
6401      }
6402    else if (e->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
6403      {
6404         bd->client.e.fetch.video_parent = 1;
6405         bd->changed = 1;
6406      }
6407    else if (e->atom == ECORE_X_ATOM_NET_WM_STATE)
6408      {
6409         bd->client.netwm.fetch.state = 1;
6410         bd->changed = 1;
6411      }
6412 #ifdef _F_USE_DESK_WINDOW_PROFILE_
6413    else if (e->atom == ECORE_X_ATOM_E_PROFILE_LIST)
6414      {
6415         bd->client.e.fetch.profile_list = 1;
6416         bd->changed = 1;
6417      }
6418 #endif
6419 #ifdef _F_ZONE_WINDOW_ROTATION_
6420    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED)
6421      {
6422         if (e_config->wm_win_rotation)
6423           {
6424              bd->client.e.fetch.rot.support = 1;
6425              bd->changed = 1;
6426           }
6427      }
6428    else if ((e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) ||
6429             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) ||
6430             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) ||
6431             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY))
6432      {
6433         if (e_config->wm_win_rotation)
6434           {
6435              bd->client.e.fetch.rot.geom_hint = 1;
6436              bd->changed = 1;
6437           }
6438      }
6439    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED)
6440      {
6441         if (e_config->wm_win_rotation)
6442           {
6443              bd->client.e.fetch.rot.app_set = 1;
6444              bd->changed = 1;
6445           }
6446      }
6447    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION)
6448      {
6449         if (e_config->wm_win_rotation)
6450           {
6451              bd->client.e.fetch.rot.preferred_rot = 1;
6452              bd->changed = 1;
6453           }
6454      }
6455    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)
6456      {
6457         if (e_config->wm_win_rotation)
6458           {
6459              bd->client.e.fetch.rot.available_rots = 1;
6460              bd->changed = 1;
6461           }
6462      }
6463 #endif
6464
6465    return ECORE_CALLBACK_PASS_ON;
6466 }
6467
6468 static Eina_Bool
6469 _e_border_cb_window_colormap(void *data  __UNUSED__,
6470                              int ev_type __UNUSED__,
6471                              void       *ev)
6472 {
6473    E_Border *bd;
6474    Ecore_X_Event_Window_Colormap *e;
6475
6476    e = ev;
6477    bd = e_border_find_by_client_window(e->win);
6478    if (!bd) return ECORE_CALLBACK_PASS_ON;
6479    return ECORE_CALLBACK_PASS_ON;
6480 }
6481
6482 static Eina_Bool
6483 _e_border_cb_window_shape(void *data  __UNUSED__,
6484                           int ev_type __UNUSED__,
6485                           void       *ev)
6486 {
6487    E_Border *bd;
6488    Ecore_X_Event_Window_Shape *e;
6489
6490    e = ev;
6491    bd = e_border_find_by_client_window(e->win);
6492
6493    if (e->type == ECORE_X_SHAPE_INPUT)
6494      {
6495         if (bd)
6496           {
6497              bd->need_shape_merge = 1;
6498 // YYY             bd->shaped_input = 1;
6499              bd->changes.shape_input = 1;
6500              bd->changed = 1;
6501           }
6502
6503         return ECORE_CALLBACK_PASS_ON;
6504      }
6505
6506    if (bd)
6507      {
6508         bd->changes.shape = 1;
6509         bd->changed = 1;
6510         return ECORE_CALLBACK_PASS_ON;
6511      }
6512    bd = e_border_find_by_window(e->win);
6513    if (bd)
6514      {
6515         bd->need_shape_export = 1;
6516         bd->changed = 1;
6517         return ECORE_CALLBACK_PASS_ON;
6518      }
6519    bd = e_border_find_by_frame_window(e->win);
6520    if (bd)
6521      {
6522         bd->need_shape_merge = 1;
6523         bd->changed = 1;
6524         return ECORE_CALLBACK_PASS_ON;
6525      }
6526    return ECORE_CALLBACK_PASS_ON;
6527 }
6528
6529 static Eina_Bool
6530 _e_border_cb_window_focus_in(void *data  __UNUSED__,
6531                              int ev_type __UNUSED__,
6532                              void       *ev)
6533 {
6534    E_Border *bd;
6535    Ecore_X_Event_Window_Focus_In *e;
6536
6537    e = ev;
6538    bd = e_border_find_by_client_window(e->win);
6539    if (!bd) return ECORE_CALLBACK_PASS_ON;
6540 #ifdef INOUTDEBUG_FOCUS
6541    {
6542       time_t t;
6543       char *ct;
6544
6545       const char *modes[] = {
6546         "MODE_NORMAL",
6547         "MODE_WHILE_GRABBED",
6548         "MODE_GRAB",
6549         "MODE_UNGRAB"
6550       };
6551       const char *details[] = {
6552         "DETAIL_ANCESTOR",
6553         "DETAIL_VIRTUAL",
6554         "DETAIL_INFERIOR",
6555         "DETAIL_NON_LINEAR",
6556         "DETAIL_NON_LINEAR_VIRTUAL",
6557         "DETAIL_POINTER",
6558         "DETAIL_POINTER_ROOT",
6559         "DETAIL_DETAIL_NONE"
6560       };
6561       t = time(NULL);
6562       ct = ctime(&t);
6563       ct[strlen(ct) - 1] = 0;
6564       DBG("FF ->IN %i 0x%x %s md=%s dt=%s\n",
6565              e->time,
6566              e->win,
6567              ct,
6568              modes[e->mode],
6569              details[e->detail]);
6570
6571       DBG("%s cb focus in %d %d\n",
6572              e_border_name_get(bd),
6573              bd->client.icccm.accepts_focus,
6574              bd->client.icccm.take_focus);
6575    }
6576 #endif
6577    _e_border_pri_raise(bd);
6578    if (e->mode == ECORE_X_EVENT_MODE_GRAB)
6579      {
6580         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
6581      }
6582    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
6583      {
6584         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
6585      }
6586
6587    /* ignore focus in from !take_focus windows, we just gave it em */
6588    /* if (!bd->client.icccm.take_focus)
6589     *   return ECORE_CALLBACK_PASS_ON; */
6590
6591    /* should be equal, maybe some clients dont reply with the proper timestamp ? */
6592    if (e->time >= focus_time)
6593      e_border_focus_set(bd, 1, 0);
6594    return ECORE_CALLBACK_PASS_ON;
6595 }
6596
6597 static Eina_Bool
6598 _e_border_cb_window_focus_out(void *data  __UNUSED__,
6599                               int ev_type __UNUSED__,
6600                               void       *ev)
6601 {
6602    E_Border *bd;
6603    Ecore_X_Event_Window_Focus_Out *e;
6604
6605    e = ev;
6606    bd = e_border_find_by_client_window(e->win);
6607    if (!bd) return ECORE_CALLBACK_PASS_ON;
6608 #ifdef INOUTDEBUG_FOCUS
6609    {
6610       time_t t;
6611       char *ct;
6612
6613       const char *modes[] = {
6614         "MODE_NORMAL",
6615         "MODE_WHILE_GRABBED",
6616         "MODE_GRAB",
6617         "MODE_UNGRAB"
6618       };
6619       const char *details[] = {
6620         "DETAIL_ANCESTOR",
6621         "DETAIL_VIRTUAL",
6622         "DETAIL_INFERIOR",
6623         "DETAIL_NON_LINEAR",
6624         "DETAIL_NON_LINEAR_VIRTUAL",
6625         "DETAIL_POINTER",
6626         "DETAIL_POINTER_ROOT",
6627         "DETAIL_DETAIL_NONE"
6628       };
6629       t = time(NULL);
6630       ct = ctime(&t);
6631       ct[strlen(ct) - 1] = 0;
6632       DBG("FF <-OUT %i 0x%x %s md=%s dt=%s",
6633              e->time,
6634              e->win,
6635              ct,
6636              modes[e->mode],
6637              details[e->detail]);
6638
6639       DBG("%s cb focus out %d %d",
6640              e_border_name_get(bd),
6641              bd->client.icccm.accepts_focus,
6642              bd->client.icccm.take_focus);
6643    }
6644 #endif
6645    _e_border_pri_norm(bd);
6646    if (e->mode == ECORE_X_EVENT_MODE_NORMAL)
6647      {
6648         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
6649         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
6650           return ECORE_CALLBACK_PASS_ON;
6651         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
6652           return ECORE_CALLBACK_PASS_ON;
6653      }
6654    else if (e->mode == ECORE_X_EVENT_MODE_GRAB)
6655      {
6656         if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR) return ECORE_CALLBACK_PASS_ON;
6657         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
6658           return ECORE_CALLBACK_PASS_ON;
6659         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
6660           return ECORE_CALLBACK_PASS_ON;
6661         else if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
6662           return ECORE_CALLBACK_PASS_ON;
6663         else if (e->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
6664           return ECORE_CALLBACK_PASS_ON;
6665      }
6666    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
6667      {
6668         /* for firefox/thunderbird (xul) menu walking */
6669         /* NB: why did i disable this before? */
6670         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
6671         else if (e->detail == ECORE_X_EVENT_DETAIL_POINTER)
6672           return ECORE_CALLBACK_PASS_ON;
6673      }
6674    else if (e->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
6675      {
6676         if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR) return ECORE_CALLBACK_PASS_ON;
6677         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
6678           return ECORE_CALLBACK_PASS_ON;
6679      }
6680    e_border_focus_set(bd, 0, 0);
6681    return ECORE_CALLBACK_PASS_ON;
6682 }
6683
6684 #if _F_BORDER_CLIP_TO_ZONE_
6685 static void
6686 _e_border_shape_input_clip_to_zone(E_Border *bd)
6687 {
6688    /* if (!(e_config->window_out_of_vscreen_limits_partly)) return; */
6689    if (!(bd->visible))
6690      return;
6691
6692    if (!(E_CONTAINS(bd->zone->x, bd->zone->y,
6693                     bd->zone->w, bd->zone->h,
6694                     bd->x, bd->y, bd->w, bd->h)))
6695      {
6696         int x, y, w, h;
6697         x = bd->x; y = bd->y; w = bd->w; h = bd->h;
6698         E_RECTS_CLIP_TO_RECT(x, y, w, h,
6699                              bd->zone->x, bd->zone->y,
6700                              bd->zone->w, bd->zone->h);
6701         x -= bd->x;
6702         y -= bd->y;
6703         ecore_x_window_shape_input_rectangle_set(bd->bg_win, x, y, w, h);
6704         ecore_x_window_shape_input_rectangle_set(bd->win, x, y, w, h);
6705      }
6706    else
6707      {
6708         ecore_x_window_shape_input_rectangle_set(bd->bg_win, 0, 0, bd->w, bd->h);
6709         ecore_x_window_shape_input_rectangle_set(bd->win, 0, 0, bd->w, bd->h);
6710      }
6711 }
6712 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
6713
6714 static Eina_Bool
6715 _e_border_cb_client_message(void *data  __UNUSED__,
6716                             int ev_type __UNUSED__,
6717                             void       *ev)
6718 {
6719    Ecore_X_Event_Client_Message *e;
6720    E_Border *bd;
6721
6722    e = ev;
6723 #ifdef _F_DEICONIFY_APPROVE_
6724    if (e->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
6725      {
6726         if (!e_config->deiconify_approve) return ECORE_CALLBACK_PASS_ON;
6727
6728         bd = e_border_find_by_client_window(e->win);
6729         if (bd)
6730           {
6731              if (bd->client.e.state.deiconify_approve.support)
6732                {
6733                   if (e->data.l[1] != 1) return ECORE_CALLBACK_PASS_ON;
6734                   if (bd->client.e.state.deiconify_approve.wait_timer)
6735                     {
6736                        ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer);
6737                        bd->client.e.state.deiconify_approve.wait_timer = NULL;
6738                     }
6739                   bd->client.e.state.deiconify_approve.render_done = 1;
6740                   e_border_uniconify(bd);
6741                }
6742           }
6743         return ECORE_CALLBACK_PASS_ON;
6744      }
6745 #endif
6746
6747 #ifdef _F_ZONE_WINDOW_ROTATION_
6748    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
6749
6750    bd = e_border_find_by_client_window(e->win);
6751    if (!bd)
6752      {
6753         if (e_config->wm_win_rotation)
6754           {
6755              Ecore_X_Event_Client_Message *msg = NULL;
6756              Ecore_X_Atom t = e->message_type;
6757              if ((t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)  ||
6758                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE) ||
6759                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)   ||
6760                  (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE))
6761                {
6762                   msg = E_NEW(Ecore_X_Event_Client_Message, 1);
6763                   if (!msg) return ECORE_CALLBACK_PASS_ON;
6764
6765                   msg->win = e->win;
6766                   msg->message_type = e->message_type;
6767                   msg->data.l[0] = e->data.l[0];
6768                   msg->data.l[1] = e->data.l[1];
6769                   msg->data.l[2] = e->data.l[2];
6770                   msg->data.l[3] = e->data.l[3];
6771                   msg->data.l[4] = e->data.l[4];
6772                   rot.msgs = eina_list_append(rot.msgs, msg);
6773
6774                   rot.fetch = EINA_TRUE;
6775                }
6776           }
6777         return ECORE_CALLBACK_PASS_ON;
6778      }
6779
6780    if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE)
6781      {
6782         ELBF(ELBT_ROT, 0, e->data.l[0], "GET ROT_DONE a%d %dx%d zone_a:%d",
6783              e->data.l[1], e->data.l[2], e->data.l[3], bd->zone->rot.curr);
6784
6785         if (e_config->wm_win_rotation)
6786           {
6787              if ((int)e->data.l[1] == bd->client.e.state.rot.curr)
6788                _e_border_rotation_list_remove(bd);
6789           }
6790      }
6791 #endif
6792    return ECORE_CALLBACK_PASS_ON;
6793 }
6794
6795 static Eina_Bool
6796 _e_border_cb_window_state_request(void *data  __UNUSED__,
6797                                   int ev_type __UNUSED__,
6798                                   void       *ev)
6799 {
6800    E_Border *bd;
6801    Ecore_X_Event_Window_State_Request *e;
6802    int i;
6803
6804    e = ev;
6805    bd = e_border_find_by_client_window(e->win);
6806    if (!bd) return ECORE_CALLBACK_PASS_ON;
6807
6808    for (i = 0; i < 2; i++)
6809      e_hints_window_state_update(bd, e->state[i], e->action);
6810
6811    return ECORE_CALLBACK_PASS_ON;
6812 }
6813
6814 static Eina_Bool
6815 _e_border_cb_window_move_resize_request(void *data  __UNUSED__,
6816                                         int ev_type __UNUSED__,
6817                                         void       *ev)
6818 {
6819    E_Border *bd;
6820    Ecore_X_Event_Window_Move_Resize_Request *e;
6821
6822    e = ev;
6823    bd = e_border_find_by_client_window(e->win);
6824    if (!bd) return ECORE_CALLBACK_PASS_ON;
6825
6826    if ((bd->shaded) || (bd->shading) ||
6827        (bd->fullscreen) || (bd->moving) ||
6828        (bd->resize_mode != RESIZE_NONE))
6829      return ECORE_CALLBACK_PASS_ON;
6830
6831    if ((e->button >= 1) && (e->button <= 3))
6832      {
6833         bd->mouse.last_down[e->button - 1].mx = e->x;
6834         bd->mouse.last_down[e->button - 1].my = e->y;
6835         bd->mouse.last_down[e->button - 1].x = bd->x;
6836         bd->mouse.last_down[e->button - 1].y = bd->y;
6837         bd->mouse.last_down[e->button - 1].w = bd->w;
6838         bd->mouse.last_down[e->button - 1].h = bd->h;
6839      }
6840    else
6841      {
6842         bd->moveinfo.down.x = bd->x;
6843         bd->moveinfo.down.y = bd->y;
6844         bd->moveinfo.down.w = bd->w;
6845         bd->moveinfo.down.h = bd->h;
6846      }
6847    bd->mouse.current.mx = e->x;
6848    bd->mouse.current.my = e->y;
6849    bd->moveinfo.down.button = e->button;
6850    bd->moveinfo.down.mx = e->x;
6851    bd->moveinfo.down.my = e->y;
6852    grabbed = 1;
6853
6854    if (!bd->lock_user_stacking)
6855      e_border_raise(bd);
6856
6857    if (e->direction == MOVE)
6858      {
6859         bd->cur_mouse_action = e_action_find("window_move");
6860         if (bd->cur_mouse_action)
6861           {
6862              if ((!bd->cur_mouse_action->func.end_mouse) &&
6863                  (!bd->cur_mouse_action->func.end))
6864                bd->cur_mouse_action = NULL;
6865              if (bd->cur_mouse_action)
6866                {
6867                   e_object_ref(E_OBJECT(bd->cur_mouse_action));
6868                   bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
6869                }
6870           }
6871         return ECORE_CALLBACK_PASS_ON;
6872      }
6873
6874    if (!_e_border_resize_begin(bd))
6875      return ECORE_CALLBACK_PASS_ON;
6876
6877    switch (e->direction)
6878      {
6879       case RESIZE_TL:
6880         bd->resize_mode = RESIZE_TL;
6881         GRAV_SET(bd, ECORE_X_GRAVITY_SE);
6882         break;
6883
6884       case RESIZE_T:
6885         bd->resize_mode = RESIZE_T;
6886         GRAV_SET(bd, ECORE_X_GRAVITY_S);
6887         break;
6888
6889       case RESIZE_TR:
6890         bd->resize_mode = RESIZE_TR;
6891         GRAV_SET(bd, ECORE_X_GRAVITY_SW);
6892         break;
6893
6894       case RESIZE_R:
6895         bd->resize_mode = RESIZE_R;
6896         GRAV_SET(bd, ECORE_X_GRAVITY_W);
6897         break;
6898
6899       case RESIZE_BR:
6900         bd->resize_mode = RESIZE_BR;
6901         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
6902         break;
6903
6904       case RESIZE_B:
6905         bd->resize_mode = RESIZE_B;
6906         GRAV_SET(bd, ECORE_X_GRAVITY_N);
6907         break;
6908
6909       case RESIZE_BL:
6910         bd->resize_mode = RESIZE_BL;
6911         GRAV_SET(bd, ECORE_X_GRAVITY_NE);
6912         break;
6913
6914       case RESIZE_L:
6915         bd->resize_mode = RESIZE_L;
6916         GRAV_SET(bd, ECORE_X_GRAVITY_E);
6917         break;
6918
6919       default:
6920         return ECORE_CALLBACK_PASS_ON;
6921      }
6922
6923    bd->cur_mouse_action = e_action_find("window_resize");
6924    if (bd->cur_mouse_action)
6925      {
6926         if ((!bd->cur_mouse_action->func.end_mouse) &&
6927             (!bd->cur_mouse_action->func.end))
6928           bd->cur_mouse_action = NULL;
6929      }
6930    if (bd->cur_mouse_action)
6931      e_object_ref(E_OBJECT(bd->cur_mouse_action));
6932
6933    return ECORE_CALLBACK_PASS_ON;
6934 }
6935
6936 static Eina_Bool
6937 _e_border_cb_desktop_change(void *data  __UNUSED__,
6938                             int ev_type __UNUSED__,
6939                             void       *ev)
6940 {
6941    E_Border *bd;
6942    Ecore_X_Event_Desktop_Change *e;
6943
6944    e = ev;
6945    bd = e_border_find_by_client_window(e->win);
6946    if (bd)
6947      {
6948         if (e->desk == 0xffffffff)
6949           e_border_stick(bd);
6950         else if ((int)e->desk < (bd->zone->desk_x_count * bd->zone->desk_y_count))
6951           {
6952              E_Desk *desk;
6953
6954              desk = e_desk_at_pos_get(bd->zone, e->desk);
6955              if (desk)
6956                e_border_desk_set(bd, desk);
6957           }
6958      }
6959    else
6960      {
6961         ecore_x_netwm_desktop_set(e->win, e->desk);
6962      }
6963    return ECORE_CALLBACK_PASS_ON;
6964 }
6965
6966 static Eina_Bool
6967 _e_border_cb_sync_alarm(void *data  __UNUSED__,
6968                         int ev_type __UNUSED__,
6969                         void       *ev)
6970 {
6971    E_Border *bd;
6972    Ecore_X_Event_Sync_Alarm *e;
6973    unsigned int serial;
6974
6975    e = ev;
6976    bd = e_border_find_by_alarm(e->alarm);
6977    if (!bd) return ECORE_CALLBACK_PASS_ON;
6978
6979    if (bd->client.netwm.sync.wait)
6980      bd->client.netwm.sync.wait--;
6981
6982    if (ecore_x_sync_counter_query(bd->client.netwm.sync.counter, &serial))
6983      {
6984         E_Border_Pending_Move_Resize *pnd = NULL;
6985
6986         /* skip pending for which we didn't get a reply */
6987         while (bd->pending_move_resize)
6988           {
6989              pnd = bd->pending_move_resize->data;
6990              bd->pending_move_resize = eina_list_remove(bd->pending_move_resize, pnd);
6991
6992              if (serial == pnd->serial)
6993                break;
6994
6995              E_FREE(pnd);
6996           }
6997
6998         if (pnd)
6999           {
7000              bd->x = pnd->x;
7001              bd->y = pnd->y;
7002              bd->w = pnd->w;
7003              bd->h = pnd->h;
7004              bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
7005              bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
7006              E_FREE(pnd);
7007           }
7008      }
7009
7010    bd->changes.size = 1;
7011    bd->changes.pos = 1;
7012
7013    _e_border_eval(bd);
7014    evas_render(bd->bg_evas);
7015
7016    ecore_x_pointer_xy_get(e_manager_current_get()->root,
7017                           &bd->mouse.current.mx,
7018                           &bd->mouse.current.my);
7019
7020    bd->client.netwm.sync.send_time = ecore_loop_time_get();
7021    _e_border_resize_handle(bd);
7022
7023    return ECORE_CALLBACK_PASS_ON;
7024 }
7025
7026 static Eina_Bool
7027 _e_border_cb_efreet_cache_update(void *data  __UNUSED__,
7028                                  int ev_type __UNUSED__,
7029                                  void *ev    __UNUSED__)
7030 {
7031    Eina_List *l;
7032    E_Border *bd;
7033
7034    /* mark all borders for desktop/icon updates */
7035    EINA_LIST_FOREACH(borders, l, bd)
7036      {
7037         if (bd->desktop)
7038           {
7039              efreet_desktop_free(bd->desktop);
7040              bd->desktop = NULL;
7041           }
7042         bd->changes.icon = 1;
7043         bd->changed = 1;
7044      }
7045    /*
7046       e_init_status_set(_("Desktop files scan done"));
7047       e_init_done();
7048     */
7049    return ECORE_CALLBACK_PASS_ON;
7050 }
7051
7052 static Eina_Bool
7053 _e_border_cb_config_icon_theme(void *data  __UNUSED__,
7054                                int ev_type __UNUSED__,
7055                                void *ev    __UNUSED__)
7056 {
7057    Eina_List *l;
7058    E_Border *bd;
7059
7060    /* mark all borders for desktop/icon updates */
7061    EINA_LIST_FOREACH(borders, l, bd)
7062      {
7063         bd->changes.icon = 1;
7064         bd->changed = 1;
7065      }
7066    return ECORE_CALLBACK_PASS_ON;
7067 }
7068
7069 static Eina_Bool
7070 _e_border_cb_pointer_warp(void *data  __UNUSED__,
7071                           int ev_type __UNUSED__,
7072                           void       *ev)
7073 {
7074    E_Event_Pointer_Warp *e;
7075
7076    e = ev;
7077    if (!bdmove) return ECORE_CALLBACK_PASS_ON;
7078    e_border_move(bdmove, bdmove->x + (e->curr.x - e->prev.x), bdmove->y + (e->curr.y - e->prev.y));
7079    return ECORE_CALLBACK_PASS_ON;
7080 }
7081
7082 static void
7083 _e_border_cb_signal_bind(void            *data,
7084                          Evas_Object *obj __UNUSED__,
7085                          const char      *emission,
7086                          const char      *source)
7087 {
7088    E_Border *bd;
7089
7090    bd = data;
7091    if (e_dnd_active()) return;
7092    e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd),
7093                             emission, source);
7094 }
7095
7096 static Eina_Bool
7097 _e_border_cb_mouse_in(void    *data,
7098                       int type __UNUSED__,
7099                       void    *event)
7100 {
7101    Ecore_X_Event_Mouse_In *ev;
7102    E_Border *bd;
7103
7104    ev = event;
7105    bd = data;
7106 #ifdef INOUTDEBUG_MOUSE
7107    {
7108       time_t t;
7109       char *ct;
7110
7111       const char *modes[] = {
7112          "MODE_NORMAL",
7113          "MODE_WHILE_GRABBED",
7114          "MODE_GRAB",
7115          "MODE_UNGRAB"
7116       };
7117       const char *details[] = {
7118          "DETAIL_ANCESTOR",
7119          "DETAIL_VIRTUAL",
7120          "DETAIL_INFERIOR",
7121          "DETAIL_NON_LINEAR",
7122          "DETAIL_NON_LINEAR_VIRTUAL",
7123          "DETAIL_POINTER",
7124          "DETAIL_POINTER_ROOT",
7125          "DETAIL_DETAIL_NONE"
7126       };
7127       t = time(NULL);
7128       ct = ctime(&t);
7129       ct[strlen(ct) - 1] = 0;
7130       DBG("@@ ->IN 0x%x 0x%x %s md=%s dt=%s",
7131              ev->win, ev->event_win,
7132              ct,
7133              modes[ev->mode],
7134              details[ev->detail]);
7135    }
7136 #endif
7137    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7138    if (ev->event_win == bd->win)
7139      {
7140         e_focus_event_mouse_in(bd);
7141      }
7142 #if 0
7143    if ((ev->win != bd->win) &&
7144        (ev->win != bd->event_win) &&
7145        (ev->event_win != bd->win) &&
7146        (ev->event_win != bd->event_win))
7147      return ECORE_CALLBACK_PASS_ON;
7148 #else
7149    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7150 #endif
7151    bd->mouse.current.mx = ev->root.x;
7152    bd->mouse.current.my = ev->root.y;
7153    if (!bd->bg_evas_in)
7154      {
7155         evas_event_feed_mouse_in(bd->bg_evas, ev->time, NULL);
7156         bd->bg_evas_in = EINA_TRUE;
7157      }
7158    return ECORE_CALLBACK_PASS_ON;
7159 }
7160
7161 static Eina_Bool
7162 _e_border_cb_mouse_out(void    *data,
7163                        int type __UNUSED__,
7164                        void    *event)
7165 {
7166    Ecore_X_Event_Mouse_Out *ev;
7167    E_Border *bd;
7168
7169    ev = event;
7170    bd = data;
7171 #ifdef INOUTDEBUG_MOUSE
7172    {
7173       time_t t;
7174       char *ct;
7175
7176       const char *modes[] = {
7177          "MODE_NORMAL",
7178          "MODE_WHILE_GRABBED",
7179          "MODE_GRAB",
7180          "MODE_UNGRAB"
7181       };
7182       const char *details[] = {
7183          "DETAIL_ANCESTOR",
7184          "DETAIL_VIRTUAL",
7185          "DETAIL_INFERIOR",
7186          "DETAIL_NON_LINEAR",
7187          "DETAIL_NON_LINEAR_VIRTUAL",
7188          "DETAIL_POINTER",
7189          "DETAIL_POINTER_ROOT",
7190          "DETAIL_DETAIL_NONE"
7191       };
7192       t = time(NULL);
7193       ct = ctime(&t);
7194       ct[strlen(ct) - 1] = 0;
7195       DBG("@@ <-OUT 0x%x 0x%x %s md=%s dt=%s",
7196              ev->win, ev->event_win,
7197              ct,
7198              modes[ev->mode],
7199              details[ev->detail]);
7200    }
7201 #endif
7202    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7203    if (ev->event_win == bd->win)
7204      {
7205         if (bd->fullscreen)
7206           return ECORE_CALLBACK_PASS_ON;
7207         if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
7208             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7209           return ECORE_CALLBACK_PASS_ON;
7210         if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7211           return ECORE_CALLBACK_PASS_ON;
7212         if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
7213             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7214           return ECORE_CALLBACK_PASS_ON;
7215         e_focus_event_mouse_out(bd);
7216      }
7217 #if 0
7218    if ((ev->win != bd->win) &&
7219        (ev->win != bd->event_win) &&
7220        (ev->event_win != bd->win) &&
7221        (ev->event_win != bd->event_win))
7222      return ECORE_CALLBACK_PASS_ON;
7223 #else
7224    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7225 #endif
7226    bd->mouse.current.mx = ev->root.x;
7227    bd->mouse.current.my = ev->root.y;
7228    if (bd->bg_evas_in)
7229      {
7230         if (!((evas_event_down_count_get(bd->bg_evas) > 0) &&
7231               (!((ev->mode == ECORE_X_EVENT_MODE_GRAB) &&
7232                  (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)))))
7233           {
7234              if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7235                evas_event_feed_mouse_cancel(bd->bg_evas, ev->time, NULL);
7236              evas_event_feed_mouse_out(bd->bg_evas, ev->time, NULL);
7237              bd->bg_evas_in = EINA_FALSE;
7238           }
7239      }
7240    return ECORE_CALLBACK_PASS_ON;
7241 }
7242
7243 static Eina_Bool
7244 _e_border_cb_mouse_wheel(void    *data,
7245                          int type __UNUSED__,
7246                          void    *event)
7247 {
7248    Ecore_Event_Mouse_Wheel *ev;
7249    E_Border *bd;
7250
7251    ev = event;
7252    bd = data;
7253    if ((ev->event_window == bd->win) ||
7254        (ev->event_window == bd->event_win))
7255      {
7256         bd->mouse.current.mx = ev->root.x;
7257         bd->mouse.current.my = ev->root.y;
7258         if (!bd->cur_mouse_action)
7259           e_bindings_wheel_event_handle(E_BINDING_CONTEXT_WINDOW,
7260                                         E_OBJECT(bd), ev);
7261      }
7262    evas_event_feed_mouse_wheel(bd->bg_evas, ev->direction, ev->z, ev->timestamp, NULL);
7263    return ECORE_CALLBACK_PASS_ON;
7264 }
7265
7266 static Eina_Bool
7267 _e_border_cb_mouse_down(void    *data,
7268                         int type __UNUSED__,
7269                         void    *event)
7270 {
7271    Ecore_Event_Mouse_Button *ev;
7272    E_Border *bd;
7273
7274    ev = event;
7275    bd = data;
7276    if ((ev->event_window == bd->win) ||
7277        (ev->event_window == bd->event_win))
7278      {
7279         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7280           {
7281              bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7282              bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7283              bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7284              bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7285              bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7286              bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7287           }
7288         else
7289           {
7290              bd->moveinfo.down.x = bd->x + bd->fx.x;
7291              bd->moveinfo.down.y = bd->y + bd->fx.y;
7292              bd->moveinfo.down.w = bd->w;
7293              bd->moveinfo.down.h = bd->h;
7294           }
7295         bd->mouse.current.mx = ev->root.x;
7296         bd->mouse.current.my = ev->root.y;
7297         if (!bd->cur_mouse_action)
7298           {
7299              bd->cur_mouse_action =
7300                e_bindings_mouse_down_event_handle(E_BINDING_CONTEXT_WINDOW,
7301                                                   E_OBJECT(bd), ev);
7302              if (bd->cur_mouse_action)
7303                {
7304                   if ((!bd->cur_mouse_action->func.end_mouse) &&
7305                       (!bd->cur_mouse_action->func.end))
7306                     bd->cur_mouse_action = NULL;
7307                   if (bd->cur_mouse_action)
7308                     e_object_ref(E_OBJECT(bd->cur_mouse_action));
7309                }
7310           }
7311         e_focus_event_mouse_down(bd);
7312      }
7313    if (ev->window != ev->event_window)
7314      {
7315         return 1;
7316      }
7317    if ((ev->window != bd->event_win) && (ev->event_window != bd->win))
7318      {
7319         return 1;
7320      }
7321    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7322      {
7323         bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7324         bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7325         bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7326         bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7327         bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7328         bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7329      }
7330    else
7331      {
7332         bd->moveinfo.down.x = bd->x + bd->fx.x;
7333         bd->moveinfo.down.y = bd->y + bd->fx.y;
7334         bd->moveinfo.down.w = bd->w;
7335         bd->moveinfo.down.h = bd->h;
7336      }
7337    bd->mouse.current.mx = ev->root.x;
7338    bd->mouse.current.my = ev->root.y;
7339 /*
7340    if (bd->moving)
7341      {
7342      }
7343    else if (bd->resize_mode != RESIZE_NONE)
7344      {
7345      }
7346    else
7347  */
7348    {
7349       Evas_Button_Flags flags = EVAS_BUTTON_NONE;
7350
7351       if (ev->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
7352       if (ev->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
7353       evas_event_feed_mouse_down(bd->bg_evas, ev->buttons, flags, ev->timestamp, NULL);
7354    }
7355    return ECORE_CALLBACK_PASS_ON;
7356 }
7357
7358 static Eina_Bool
7359 _e_border_cb_mouse_up(void    *data,
7360                       int type __UNUSED__,
7361                       void    *event)
7362 {
7363    Ecore_Event_Mouse_Button *ev;
7364    E_Border *bd;
7365
7366    ev = event;
7367    bd = data;
7368    if ((ev->event_window == bd->win) ||
7369        (ev->event_window == bd->event_win))
7370      {
7371         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7372           {
7373              bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7374              bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7375              bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7376              bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7377           }
7378         bd->mouse.current.mx = ev->root.x;
7379         bd->mouse.current.my = ev->root.y;
7380         /* also we dont pass the same params that went in - then again that */
7381         /* should be ok as we are just ending the action if it has an end */
7382         if (bd->cur_mouse_action)
7383           {
7384              if (bd->cur_mouse_action->func.end_mouse)
7385                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", ev);
7386              else if (bd->cur_mouse_action->func.end)
7387                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
7388              e_object_unref(E_OBJECT(bd->cur_mouse_action));
7389              bd->cur_mouse_action = NULL;
7390           }
7391         else
7392           {
7393              if (!e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd), ev))
7394                e_focus_event_mouse_up(bd);
7395           }
7396      }
7397    if (ev->window != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7398    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7399      {
7400         bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7401         bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7402         bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7403         bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7404      }
7405    bd->mouse.current.mx = ev->root.x;
7406    bd->mouse.current.my = ev->root.y;
7407
7408    bd->drag.start = 0;
7409
7410    evas_event_feed_mouse_up(bd->bg_evas, ev->buttons, EVAS_BUTTON_NONE, ev->timestamp, NULL);
7411    return ECORE_CALLBACK_PASS_ON;
7412 }
7413
7414 static void
7415 _e_border_stay_within_container(E_Border *bd, int x, int y, int *new_x, int *new_y)
7416 {
7417 #ifdef _F_BORDER_CLIP_TO_ZONE_
7418    int new_x_max, new_y_max;
7419    int new_x_min, new_y_min;
7420    int margin_x, margin_y;
7421
7422    margin_x = bd->w - 100;
7423    margin_y = bd->h - 100;
7424
7425    new_x_max = bd->zone->x + bd->zone->w - bd->w + margin_x;
7426    new_x_min = bd->zone->x - margin_x;
7427    new_y_max = bd->zone->y + bd->zone->h - bd->h + margin_y;
7428    new_y_min = bd->zone->y - margin_y;
7429
7430    if (x >= new_x_max)      *new_x = new_x_max;
7431    else if (x <= new_x_min) *new_x = new_x_min;
7432
7433    if (y >= new_y_max)      *new_y = new_y_max;
7434    else if (y <= new_y_min) *new_y = new_y_min;
7435 #endif
7436 }
7437
7438 static Eina_Bool
7439 _e_border_cb_mouse_move(void    *data,
7440                         int type __UNUSED__,
7441                         void    *event)
7442 {
7443    Ecore_Event_Mouse_Move *ev;
7444    E_Border *bd;
7445
7446    ev = event;
7447    bd = data;
7448    if ((ev->window != bd->event_win) &&
7449        (ev->event_window != bd->win)) return ECORE_CALLBACK_PASS_ON;
7450    bd->mouse.current.mx = ev->root.x;
7451    bd->mouse.current.my = ev->root.y;
7452    if (bd->moving)
7453      {
7454         int x, y, new_x, new_y;
7455         int new_w, new_h;
7456         Eina_List *skiplist = NULL;
7457 #if 0
7458         // FIXME: remove? sync what for when only moving?
7459         if ((ecore_loop_time_get() - bd->client.netwm.sync.time) > 0.5)
7460           bd->client.netwm.sync.wait = 0;
7461         if ((bd->client.netwm.sync.request) &&
7462             (bd->client.netwm.sync.alarm) &&
7463             (bd->client.netwm.sync.wait > 1)) return ECORE_CALLBACK_PASS_ON;
7464 #endif
7465         if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
7466           {
7467              x = bd->mouse.last_down[bd->moveinfo.down.button - 1].x +
7468                (bd->mouse.current.mx - bd->moveinfo.down.mx);
7469              y = bd->mouse.last_down[bd->moveinfo.down.button - 1].y +
7470                (bd->mouse.current.my - bd->moveinfo.down.my);
7471           }
7472         else
7473           {
7474              x = bd->moveinfo.down.x +
7475                (bd->mouse.current.mx - bd->moveinfo.down.mx);
7476              y = bd->moveinfo.down.y +
7477                (bd->mouse.current.my - bd->moveinfo.down.my);
7478           }
7479         new_x = x;
7480         new_y = y;
7481
7482 #ifdef _F_USE_RESIST_MAGNETIC_EFFECT_
7483         skiplist = eina_list_append(skiplist, bd);
7484         e_resist_container_border_position(bd->zone->container, skiplist,
7485                                            bd->x, bd->y, bd->w, bd->h,
7486                                            x, y, bd->w, bd->h,
7487                                            &new_x, &new_y, &new_w, &new_h);
7488         eina_list_free(skiplist);
7489
7490         _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
7491 #else
7492         /* if (e_config->window_out_of_vscreen_limits_partly) */
7493         if (1)
7494           _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
7495         else
7496           {
7497              skiplist = eina_list_append(skiplist, bd);
7498              e_resist_container_border_position(bd->zone->container, skiplist,
7499                                                 bd->x, bd->y, bd->w, bd->h,
7500                                                 x, y, bd->w, bd->h,
7501                                                 &new_x, &new_y, &new_w, &new_h);
7502              eina_list_free(skiplist);
7503           }
7504 #endif
7505         bd->shelf_fix.x = 0;
7506         bd->shelf_fix.y = 0;
7507         bd->shelf_fix.modified = 0;
7508         e_border_move(bd, new_x, new_y);
7509         e_zone_flip_coords_handle(bd->zone, ev->root.x, ev->root.y);
7510      }
7511    else if (bd->resize_mode != RESIZE_NONE)
7512      {
7513         if ((bd->client.netwm.sync.request) &&
7514             (bd->client.netwm.sync.alarm))
7515           {
7516              if ((ecore_loop_time_get() - bd->client.netwm.sync.send_time) > 0.5)
7517                {
7518                   E_Border_Pending_Move_Resize *pnd;
7519
7520                   if (bd->pending_move_resize)
7521                     {
7522                        bd->changes.pos = 1;
7523                        bd->changes.size = 1;
7524                        bd->changed = 1;
7525                        _e_border_client_move_resize_send(bd);
7526                     }
7527                   EINA_LIST_FREE(bd->pending_move_resize, pnd)
7528                     E_FREE(pnd);
7529
7530                   bd->client.netwm.sync.wait = 0;
7531                }
7532              /* sync.wait is incremented when resize_handle sends
7533               * sync-request and decremented by sync-alarm cb. so
7534               * we resize here either on initial resize, timeout or
7535               * when no new resize-request was added by sync-alarm cb.
7536               */
7537              if (!bd->client.netwm.sync.wait)
7538                _e_border_resize_handle(bd);
7539           }
7540         else
7541           _e_border_resize_handle(bd);
7542      }
7543    else
7544      {
7545         if (bd->drag.start)
7546           {
7547              if ((bd->drag.x == -1) && (bd->drag.y == -1))
7548                {
7549                   bd->drag.x = ev->root.x;
7550                   bd->drag.y = ev->root.y;
7551                }
7552              else
7553                {
7554                   int dx, dy;
7555
7556                   dx = bd->drag.x - ev->root.x;
7557                   dy = bd->drag.y - ev->root.y;
7558                   if (((dx * dx) + (dy * dy)) >
7559                       (e_config->drag_resist * e_config->drag_resist))
7560                     {
7561      /* start drag! */
7562                         if (bd->icon_object)
7563                           {
7564                              Evas_Object *o = NULL;
7565                              Evas_Coord x, y, w, h;
7566                              const char *drag_types[] = { "enlightenment/border" };
7567
7568                              e_object_ref(E_OBJECT(bd));
7569                              evas_object_geometry_get(bd->icon_object,
7570                                                       &x, &y, &w, &h);
7571                              drag_border = e_drag_new(bd->zone->container,
7572                                                       bd->x + bd->fx.x + x,
7573                                                       bd->y + bd->fx.y + y,
7574                                                       drag_types, 1, bd, -1,
7575                                                       NULL,
7576                                                       _e_border_cb_drag_finished);
7577                              o = e_border_icon_add(bd, drag_border->evas);
7578                              if (!o)
7579                                {
7580      /* FIXME: fallback icon for drag */
7581                                    o = evas_object_rectangle_add(drag_border->evas);
7582                                    evas_object_color_set(o, 255, 255, 255, 255);
7583                                }
7584                              e_drag_object_set(drag_border, o);
7585
7586                              e_drag_resize(drag_border, w, h);
7587                              e_drag_start(drag_border, bd->drag.x, bd->drag.y);
7588                           }
7589                         bd->drag.start = 0;
7590                     }
7591                }
7592           }
7593         evas_event_feed_mouse_move(bd->bg_evas, ev->x, ev->y, ev->timestamp, NULL);
7594      }
7595    return ECORE_CALLBACK_PASS_ON;
7596 }
7597
7598 static Eina_Bool
7599 _e_border_cb_grab_replay(void *data __UNUSED__,
7600                          int        type,
7601                          void      *event)
7602 {
7603    Ecore_Event_Mouse_Button *ev;
7604
7605    if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
7606    ev = event;
7607    if ((e_config->pass_click_on)
7608        || (e_config->always_click_to_raise) // this works even if not on click-to-focus
7609        || (e_config->always_click_to_focus) // this works even if not on click-to-focus
7610       )
7611      {
7612         E_Border *bd;
7613
7614         bd = e_border_find_by_window(ev->event_window);
7615         if (bd)
7616           {
7617              if (bd->cur_mouse_action)
7618                return ECORE_CALLBACK_DONE;
7619              if (ev->event_window == bd->win)
7620                {
7621                   if (!e_bindings_mouse_down_find(E_BINDING_CONTEXT_WINDOW,
7622                                                   E_OBJECT(bd), ev, NULL))
7623                     return ECORE_CALLBACK_PASS_ON;
7624                }
7625           }
7626      }
7627    return ECORE_CALLBACK_DONE;
7628 }
7629
7630 static void
7631 _e_border_cb_drag_finished(E_Drag     *drag,
7632                            int dropped __UNUSED__)
7633 {
7634    E_Border *bd;
7635
7636    bd = drag->data;
7637    e_object_unref(E_OBJECT(bd));
7638    drag_border = NULL;
7639 }
7640
7641 #ifdef _F_USE_DESK_WINDOW_PROFILE_
7642 static Eina_Bool
7643 _e_border_cb_desk_window_profile_change(void *data  __UNUSED__,
7644                                         int ev_type __UNUSED__,
7645                                         void       *ev)
7646 {
7647    E_Event_Desk_Window_Profile_Change *e;
7648    Eina_List *l;
7649    E_Border *bd;
7650
7651    e = ev;
7652    EINA_LIST_FOREACH(borders, l, bd)
7653      {
7654         if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
7655           {
7656              bd->client.e.fetch.profile_list = 1;
7657              bd->changed = 1;
7658           }
7659      }
7660    return ECORE_CALLBACK_PASS_ON;
7661 }
7662 #endif
7663
7664 #ifdef _F_ZONE_WINDOW_ROTATION_
7665 static Eina_Bool
7666 _e_border_cb_zone_rotation_change(void *data  __UNUSED__,
7667                                   int ev_type __UNUSED__,
7668                                   void       *ev)
7669 {
7670    E_Event_Zone_Rotation_Change *e = ev;
7671    Eina_Bool res = EINA_FALSE;
7672
7673    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
7674    if ((!e) || (!e->zone)) return ECORE_CALLBACK_PASS_ON;
7675
7676    res = _e_border_rotation_zone_check(e->zone);
7677    ELBF(ELBT_ROT, 0, e->zone->id, "ZONE ROT CHECK: result:%d (%d)", res, e->zone->rot.curr);
7678    if (res)
7679      {
7680         e_manager_comp_screen_lock(e_manager_current_get());
7681         res = _e_border_rotation_zone_vkbd_check(e->zone);
7682         ELBF(ELBT_ROT, 0, e->zone->id, "ZONE ROT CHECK: vkbd result:%d (%d)", res, e->zone->rot.curr);
7683         if (res)
7684           {
7685              res = _e_border_rotation_transient_for_check(rot.vkbd,
7686                                                           e->zone->rot.curr);
7687              ELBF(ELBT_ROT, 0, e->zone->id, "ZONE ROT CHECK: vkbd transient_for result:%d (%d)", res, e->zone->rot.curr);
7688           }
7689
7690         if (res)
7691           {
7692              if (rot.prepare_timer)
7693                ecore_timer_del(rot.prepare_timer);
7694              rot.prepare_timer = NULL;
7695
7696              if (rot.done_timer)
7697                ecore_timer_del(rot.done_timer);
7698              rot.done_timer = NULL;
7699
7700              ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win);
7701              ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
7702                                                            e->zone->rot.curr,
7703                                                            EINA_FALSE, 1, 1);
7704              rot.prepare_timer = ecore_timer_add(4.0f,
7705                                                  _e_border_rotation_change_prepare_timeout,
7706                                                  NULL);
7707              rot.wait_prepare_done = EINA_TRUE;
7708           }
7709         else
7710           {
7711              _e_border_rotation_list_add(e->zone, EINA_TRUE);
7712              _e_border_rotation_change_request(e->zone);
7713           }
7714      }
7715    else
7716      {
7717         /* there is no border which supports window manager rotation */
7718         e_zone_rotation_update_cancel(e->zone);
7719      }
7720    return ECORE_CALLBACK_PASS_ON;
7721 }
7722
7723 static Eina_Bool
7724 _e_border_rotation_change_prepare_timeout(void *data)
7725 {
7726    E_Zone *zone = data;
7727    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
7728
7729    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE_PREPARE", 0);
7730
7731    if ((rot.wait_prepare_done) &&
7732        (zone) &&
7733        (_e_border_rotation_list_add(zone, EINA_FALSE)))
7734      {
7735         _e_border_rotation_change_request(zone);
7736      }
7737    else
7738      {
7739         if (rot.prepare_timer)
7740           ecore_timer_del(rot.prepare_timer);
7741         rot.prepare_timer = NULL;
7742         rot.wait_prepare_done = EINA_FALSE;
7743      }
7744    return ECORE_CALLBACK_CANCEL;
7745 }
7746
7747 static void
7748 _e_border_rotation_change_request(E_Zone *zone __UNUSED__)
7749 {
7750    Eina_List *l = NULL;
7751    E_Border_Rotation_Info *info = NULL;
7752
7753    if (!e_config->wm_win_rotation) return;
7754    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
7755    rot.prepare_timer = NULL;
7756    rot.wait_prepare_done = EINA_FALSE;
7757
7758    EINA_LIST_FOREACH(rot.list, l, info)
7759      {
7760         ELBF(ELBT_ROT, 1, info->bd->client.win,
7761              "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
7762              info->ang, info->win_resize, info->w, info->h);
7763
7764         ecore_x_e_window_rotation_change_prepare_send
7765           (info->bd->client.win, info->ang,
7766           info->win_resize, info->w, info->h);
7767
7768         if (!info->bd->client.e.state.rot.pending_change_request)
7769           {
7770              ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
7771              ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
7772                                                            info->ang);
7773           }
7774      }
7775
7776    if (rot.done_timer)
7777      ecore_timer_del(rot.done_timer);
7778    rot.done_timer = ecore_timer_add(4.0f,
7779                                     _e_border_rotation_change_done_timeout,
7780                                     NULL);
7781 }
7782
7783 static void
7784 _e_border_rotation_list_remove(E_Border *bd)
7785 {
7786    Eina_List *l = NULL;
7787    E_Border_Rotation_Info *info = NULL;
7788    if (!e_config->wm_win_rotation) return;
7789
7790    EINA_LIST_FOREACH(rot.list, l, info)
7791      {
7792         if (info->bd == bd)
7793           {
7794              rot.list = eina_list_remove(rot.list, info);
7795              E_FREE(info);
7796           }
7797      }
7798
7799    if (bd->client.e.state.rot.wait_for_done)
7800      {
7801         bd->client.e.state.rot.wait_for_done = 0;
7802         if (eina_list_count(rot.list) == 0)
7803           {
7804              _e_border_rotation_change_done();
7805           }
7806      }
7807 }
7808
7809 static Eina_Bool
7810 _e_border_rotation_change_done_timeout(void *data __UNUSED__)
7811 {
7812    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
7813    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE", 0);
7814    _e_border_rotation_change_done();
7815    return ECORE_CALLBACK_CANCEL;
7816 }
7817
7818 static void
7819 _e_border_rotation_change_done(void)
7820 {
7821    E_Manager *m = NULL;
7822    E_Border_Rotation_Info *info = NULL;
7823
7824    if (!e_config->wm_win_rotation) return;
7825
7826    if (rot.prepare_timer)
7827      ecore_timer_del(rot.prepare_timer);
7828    rot.prepare_timer = NULL;
7829
7830    rot.wait_prepare_done = EINA_FALSE;
7831
7832    if (rot.done_timer)
7833      ecore_timer_del(rot.done_timer);
7834    rot.done_timer = NULL;
7835
7836    EINA_LIST_FREE(rot.list, info)
7837      {
7838         if (info->bd)
7839           {
7840              info->bd->client.e.state.rot.wait_for_done = 0;
7841              ELB(ELBT_ROT, "TIMEOUT ROT_DONE", info->bd->client.win);
7842           }
7843         E_FREE(info);
7844      }
7845
7846    rot.list = NULL;
7847
7848    m = e_manager_current_get();
7849    e_manager_comp_screen_unlock(m);
7850    e_zone_rotation_update_done(e_util_zone_current_get(m));
7851 }
7852
7853 static int
7854 _prev_angle_get(Ecore_X_Window win)
7855 {
7856    int ret, count = 0, ang = -1;
7857    unsigned char* data = NULL;
7858
7859    ret = ecore_x_window_prop_property_get
7860       (win, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
7861       ECORE_X_ATOM_CARDINAL, 32, &data, &count);
7862
7863    if ((ret) && (data) && (count))
7864      ang = ((int *)data)[0];
7865    if (data) free(data);
7866    return ang;
7867 }
7868
7869 /* get proper rotation value using preferred rotation and list of available rotations */
7870 static int
7871 _e_border_rotation_get(E_Border *bd,
7872                        int       base_ang)
7873 {
7874    int ang = -1;
7875    unsigned int i;
7876    Eina_Bool found = EINA_FALSE;
7877
7878    if (!e_config->wm_win_rotation) return ang;
7879    if (!bd->client.e.state.rot.app_set) return ang;
7880
7881    if (bd->client.e.state.rot.preferred_rot != -1)
7882      {
7883         ang = bd->client.e.state.rot.preferred_rot;
7884         ELBF(ELBT_ROT, 0, bd->client.win, "ang:%d base_ang:%d", ang, base_ang);
7885      }
7886    else if ((bd->client.e.state.rot.available_rots) &&
7887             (bd->client.e.state.rot.count))
7888      {
7889         for (i = 0; i < bd->client.e.state.rot.count; i++)
7890           {
7891              if (bd->client.e.state.rot.available_rots[i] == base_ang)
7892                {
7893                   ang = base_ang;
7894                   found = EINA_TRUE;
7895                   break;
7896                }
7897           }
7898
7899         /* do nothing. this window wants to maintain current state.
7900          * for example, window's available_rots: 0, 90, 270,
7901          * current zone rotation request: 180. the WM does nothing
7902          * for this window.
7903          */
7904         if (!found)
7905           {
7906              if (bd->client.e.state.rot.curr != -1)
7907                ang = bd->client.e.state.rot.curr;
7908              else
7909                ang = bd->client.e.state.rot.available_rots[0];
7910           }
7911      }
7912    else
7913      {
7914         /* In this case, border doesn't have a list of
7915          * available rotations, thus WM should request
7916          * rotation with '0' degree to the application.
7917          */
7918         ang = 0;
7919      }
7920
7921    return ang;
7922 }
7923
7924 #define REGION_EQUAL_TO_ZONE(a, z) \
7925    ((((a)->x) == ((z)->x)) &&      \
7926     (((a)->y) == ((z)->y)) &&      \
7927     (((a)->w) == ((z)->w)) &&      \
7928     (((a)->h) == ((z)->h)))
7929
7930 static Eina_Bool
7931 _e_border_rotation_check(E_Border *bd)
7932 {
7933    E_Zone *zone = bd->zone;
7934    int x, y, w, h, ang = 0;
7935    int diff = 0, _ang = 0;
7936    Eina_Bool resize = EINA_TRUE;
7937    Eina_Bool hint = EINA_FALSE;
7938    Eina_Bool move = EINA_TRUE;
7939
7940    if (!e_config->wm_win_rotation) return EINA_FALSE;
7941
7942    ELB(ELBT_ROT, "CHECK ROT", bd->client.win);
7943
7944    ang = zone->rot.curr;
7945
7946    if (((rot.vkbd) && (rot.vkbd == bd)) ||
7947        ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
7948      {
7949         ELBF(ELBT_ROT, 1, bd->client.win,
7950              "%s->parent:0x%08x (support:%d app_set:%d ang:%d)",
7951              (rot.vkbd == bd) ? "vkbd" : "prediction",
7952              bd->parent ? bd->parent->client.win : 0,
7953              bd->parent ? bd->parent->client.e.state.rot.support : -1,
7954              bd->parent ? bd->parent->client.e.state.rot.app_set : -1,
7955              bd->parent ? bd->parent->client.e.state.rot.curr : -1);
7956
7957         if (bd->parent)
7958           {
7959              ang = bd->parent->client.e.state.rot.curr;
7960              if ((!bd->parent->client.e.state.rot.support) &&
7961                  (!bd->parent->client.e.state.rot.app_set))
7962                {
7963                   ang = 0;
7964                }
7965           }
7966      }
7967
7968    if ((!bd->client.e.state.rot.app_set) &&
7969        (!bd->client.e.state.rot.support))
7970      {
7971         /* hack for magnifier and keyboard popup */
7972         if ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER) ||
7973             (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP))
7974           {
7975              ELB(ELBT_BD, "MAG", bd->client.win);
7976              ang = 0;
7977              if ((rot.vkbd) && (rot.vkbd->visible))
7978                ang = rot.vkbd->client.e.state.rot.curr;
7979              hint = _e_border_rotation_geom_get(bd, zone, ang, &x, &y, &w, &h, &move);
7980              if (hint)
7981                {
7982                   ELBF(ELBT_ROT, 1, bd->client.win, "MAG %d,%d %dx%d m:%d", x, y, w, h, move);
7983                   _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
7984                }
7985              return EINA_FALSE;
7986           }
7987      }
7988
7989    if (bd->client.e.state.rot.app_set)
7990      {
7991         /* utility type window should be rotated according to
7992          * rotation of the transient_for window.
7993          */
7994         if ((bd->parent) &&
7995             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
7996           {
7997              ang = bd->parent->client.e.state.rot.curr;
7998              if ((!bd->parent->client.e.state.rot.support) &&
7999                  (!bd->parent->client.e.state.rot.app_set))
8000                {
8001                   /* if transient_for window doesn't support rotation feature,
8002                    * then this window should't be rotated.
8003                    * TODO: need to check whether window supports '0' degree or not.
8004                    */
8005                   ang = 0;
8006                   ELBF(ELBT_ROT, 0, bd->client.win,
8007                        "GET ROT ang:%d Transient_For:0x%08x Not support rot",
8008                        ang, bd->parent->client.win);
8009                }
8010              else
8011                {
8012                   ang = _e_border_rotation_get(bd->parent, ang);
8013                   ELBF(ELBT_ROT, 0, bd->client.win,
8014                        "GET ROT ang:%d Transient_For:0x%08x",
8015                        ang, bd->parent->client.win);
8016                }
8017           }
8018         else
8019           {
8020              ang = _e_border_rotation_get(bd, ang);
8021              ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d",
8022                   ang, bd->parent ? bd->parent->client.win : 0,
8023                   bd->client.netwm.type);
8024           }
8025      }
8026
8027    hint = _e_border_rotation_geom_get(bd, zone, ang, &x, &y, &w, &h, &move);
8028    if (hint)
8029      _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
8030
8031    /* need to check previous rotation angle, this may be because
8032     * the window was unmapped with non-0 rotation degree.
8033     * and now, the window wants to show on the 0 degree zone,
8034     * thus the wm should request to rotate the window to 0 degree.
8035     */
8036    if (!bd->visible)
8037      {
8038         _ang = _prev_angle_get(bd->client.win);
8039         if (_ang != -1)
8040           bd->client.e.state.rot.curr = _ang;
8041         ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang);
8042      }
8043
8044    if (bd->client.e.state.rot.curr != ang)
8045      {
8046         Eina_Bool is_screen_locked = EINA_FALSE;
8047
8048         if ((rot.vkbd != bd) && (rot.vkbd_prediction != bd) &&
8049             /* check whether virtual keyboard is visible on the zone */
8050             (_e_border_rotation_zone_vkbd_check(bd->zone)) &&
8051             /* check whether virtual keyboard belongs to this border (transient_for) */
8052             (_e_border_rotation_vkbd_transient_for_check(bd)) &&
8053             /* check rotation of the virtual keyboard */
8054             (((rot.vkbd) && (rot.vkbd->client.e.state.rot.curr != ang)) ||
8055              ((rot.vkbd_prediction) && (rot.vkbd_prediction->client.e.state.rot.curr != ang))) &&
8056             (!rot.wait_prepare_done))
8057           {
8058              ELB(ELBT_ROT, "DO VKBD ROT", bd->client.win);
8059              e_manager_comp_screen_lock(e_manager_current_get());
8060              is_screen_locked = EINA_TRUE;
8061
8062              if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8063              rot.prepare_timer = NULL;
8064
8065              if (rot.done_timer) ecore_timer_del(rot.done_timer);
8066              rot.done_timer = NULL;
8067
8068              ELB(ELBT_ROT, "send rot_change_prepare", rot.vkbd_ctrl_win);
8069              ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8070                                                            bd->zone->rot.curr,
8071                                                            EINA_FALSE, 1, 1);
8072              rot.prepare_timer = ecore_timer_add(4.0f,
8073                                                  _e_border_rotation_change_prepare_timeout,
8074                                                  NULL);
8075              rot.wait_prepare_done = EINA_TRUE;
8076           }
8077
8078         bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8079         bd->client.e.state.rot.curr = ang;
8080         bd->client.e.state.rot.wait_for_done = 1;
8081
8082         diff = bd->client.e.state.rot.curr - bd->client.e.state.rot.prev;
8083         if ((diff == 180) || (diff == -180))
8084           resize = EINA_FALSE;
8085
8086         /* Check if it has size hint, full size or not, and needs to resize.
8087          * Under the below condition, replace width value with height.
8088          */
8089         if ((!hint) && (!REGION_EQUAL_TO_ZONE(bd, bd->zone)) && (resize))
8090           {
8091              x = bd->x;  y = bd->y;
8092              w = bd->w;  h = bd->h;
8093
8094              if (w == h)
8095                resize = EINA_FALSE;
8096              else
8097                {
8098                   w = bd->h;
8099                   h = bd->w;
8100
8101                   _e_border_move_resize_internal(bd, x, y, w, h,
8102                                                  EINA_TRUE, EINA_FALSE);
8103                }
8104           }
8105
8106         /* hack ... */
8107         if (bd->client.e.state.rot.app_set) resize = EINA_FALSE;
8108
8109         E_Border_Rotation_Info *info = NULL;
8110         info = E_NEW(E_Border_Rotation_Info, 1);
8111         if (info)
8112           {
8113              if (!is_screen_locked)
8114                e_manager_comp_screen_lock(e_manager_current_get());
8115
8116              info->bd = bd;
8117              info->ang = ang;
8118              info->x = x; info->y = y;
8119              info->w = w; info->h = h;
8120              info->win_resize = resize;
8121              rot.list = eina_list_append(rot.list, info);
8122
8123              if (info->win_resize)
8124                bd->client.e.state.rot.pending_change_request = 1;
8125
8126              ELBF(ELBT_ROT, 1, info->bd->client.win,
8127                   "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
8128                   info->ang, info->win_resize, info->w, info->h);
8129
8130              ecore_x_e_window_rotation_change_prepare_send
8131                 (info->bd->client.win, info->ang,
8132                  info->win_resize, info->w, info->h);
8133
8134              if (!info->bd->client.e.state.rot.pending_change_request)
8135                {
8136                   ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
8137                   ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
8138                                                                 info->ang);
8139                }
8140
8141              if (rot.done_timer)
8142                ecore_timer_del(rot.done_timer);
8143              rot.done_timer = ecore_timer_add(4.0f,
8144                                               _e_border_rotation_change_done_timeout,
8145                                               NULL);
8146           }
8147      }
8148    return EINA_TRUE;
8149 }
8150
8151 static Eina_Bool
8152 _e_border_rotation_zone_check(E_Zone *zone)
8153 {
8154    Eina_Bool wait = EINA_FALSE;
8155    E_Border_List *l = NULL;
8156    E_Border *bd = NULL;
8157
8158    if (!e_config->wm_win_rotation) return EINA_FALSE;
8159
8160    l = e_container_border_list_last(zone->container);
8161    if (!l) return EINA_FALSE;
8162    while ((bd = e_container_border_list_prev(l)))
8163      {
8164         if ((!bd) || (e_object_is_del(E_OBJECT(bd))) ||
8165             (!bd->visible) || (bd->zone != zone) ||
8166             (!E_INTERSECTS(zone->x, zone->y, zone->w, zone->h,
8167                            bd->x, bd->y, bd->w, bd->h))) continue;
8168
8169         if (((rot.vkbd) && (rot.vkbd == bd)) ||
8170             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)) ||
8171             ((REGION_EQUAL_TO_ZONE(bd, zone)) &&
8172              (bd->client.e.state.rot.preferred_rot != -1))) continue;
8173
8174         if (_e_border_rotation_border_check(bd, zone->rot.curr))
8175           {
8176              wait = EINA_TRUE;
8177              break;
8178           }
8179      }
8180    if (l) e_container_border_list_free(l);
8181
8182    return wait;
8183 }
8184
8185 // check if border is rotatable in ang.
8186 static Eina_Bool
8187 _e_border_rotation_border_check(E_Border *bd, int ang)
8188 {
8189    Eina_Bool wait = EINA_FALSE;
8190
8191    if (!bd) return wait;
8192
8193    if (((bd->client.e.state.rot.support) || (bd->client.e.state.rot.app_set)) &&
8194        /* basically WM allows only fullscreen window to rotate */
8195        ((REGION_EQUAL_TO_ZONE(bd, bd->zone)) ||
8196         /* we don't like this kind of code.
8197          * it means that the WM also allows non-fullscreen window to rotate if it sets geom hint.
8198          * such as large editable window.
8199          */
8200         ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE) && (bd->client.e.state.rot.geom_hint)) ||
8201         /* and floating mode window is also rotatable */
8202         (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) &&
8203        (bd->client.e.state.rot.preferred_rot == -1))
8204      {
8205         unsigned int i;
8206
8207         if (bd->client.e.state.rot.app_set)
8208           {
8209              if (bd->client.e.state.rot.available_rots &&
8210                  bd->client.e.state.rot.count)
8211                {
8212                   Eina_Bool found = EINA_FALSE;
8213                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8214                     {
8215                        if (bd->client.e.state.rot.available_rots[i] == ang)
8216                          {
8217                             found = EINA_TRUE;
8218                          }
8219                     }
8220                   if ((found) && (ang != bd->client.e.state.rot.curr))
8221                     {
8222                        wait = EINA_TRUE;
8223                     }
8224                   else
8225                     {
8226                        ELB(ELBT_ROT, "ROT CANCEL for preferred rot", bd->client.win);
8227                        wait = EINA_FALSE;
8228                     }
8229                }
8230           }
8231         else
8232           {
8233              ELB(ELBT_ROT, "DO ROT", 0);
8234              wait = EINA_TRUE;
8235           }
8236      }
8237
8238    return wait;
8239 }
8240
8241 /* check whether virtual keyboard is visible on the zone */
8242 static Eina_Bool
8243 _e_border_rotation_zone_vkbd_check(E_Zone *zone)
8244 {
8245    if (!e_config->wm_win_rotation) return EINA_FALSE;
8246
8247    if ((rot.vkbd_ctrl_win) &&
8248        (rot.vkbd) &&
8249        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8250        (rot.vkbd->visible) &&
8251        (rot.vkbd->zone == zone) &&
8252        (E_INTERSECTS(zone->x, zone->y,
8253                      zone->w, zone->h,
8254                      rot.vkbd->x, rot.vkbd->y,
8255                      rot.vkbd->w, rot.vkbd->h)))
8256      {
8257         return EINA_TRUE;
8258      }
8259    return EINA_FALSE;
8260 }
8261
8262 /* check whether prediction keyboard is visible on the zone */
8263 static Eina_Bool
8264 _e_border_rotation_zone_prediction_check(E_Zone *zone)
8265 {
8266    if (!e_config->wm_win_rotation) return EINA_FALSE;
8267
8268    if ((rot.vkbd_ctrl_win) &&
8269        (rot.vkbd_prediction) &&
8270        (!e_object_is_del(E_OBJECT(rot.vkbd_prediction))) &&
8271        (rot.vkbd_prediction->visible) &&
8272        (rot.vkbd_prediction->zone == zone) &&
8273        (E_INTERSECTS(zone->x, zone->y,
8274                      zone->w, zone->h,
8275                      rot.vkbd_prediction->x, rot.vkbd_prediction->y,
8276                      rot.vkbd_prediction->w, rot.vkbd_prediction->h)))
8277      {
8278         return EINA_TRUE;
8279      }
8280    return EINA_FALSE;
8281 }
8282
8283 /* check whether border is parent of the virtual keyboard */
8284 static Eina_Bool
8285 _e_border_rotation_vkbd_transient_for_check(E_Border *bd)
8286 {
8287    if (!e_config->wm_win_rotation) return EINA_FALSE;
8288
8289    if (rot.vkbd_ctrl_win)
8290      {
8291         if ((rot.vkbd) && (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8292             (rot.vkbd != bd))
8293           {
8294              if (rot.vkbd->parent == bd)
8295                return EINA_TRUE;
8296           }
8297
8298         if ((rot.vkbd_prediction) && (!e_object_is_del(E_OBJECT(rot.vkbd_prediction))) &&
8299             (rot.vkbd_prediction != bd))
8300           {
8301              /* bug! but i can't fix it */
8302              if (rot.vkbd_prediction == bd)
8303                return EINA_TRUE;
8304           }
8305      }
8306
8307    return EINA_FALSE;
8308 }
8309
8310 // check if bd's parent is rotatable.
8311 static Eina_Bool
8312 _e_border_rotation_transient_for_check(E_Border *bd, int ang)
8313 {
8314    Eina_Bool ret = EINA_FALSE;
8315
8316    if (!e_config->wm_win_rotation) return EINA_FALSE;
8317    if (!bd) return EINA_FALSE;
8318
8319    if (!bd->parent) ret = EINA_TRUE;
8320    else
8321      {
8322         if (_e_border_rotation_border_check(bd->parent, ang))
8323           ret = EINA_TRUE;
8324      }
8325
8326    return ret;
8327 }
8328
8329 static Eina_Bool
8330 _e_border_rotation_list_add(E_Zone *zone, Eina_Bool without_vkbd)
8331 {
8332    Eina_Bool wait = EINA_FALSE;
8333    E_Border_List *l = NULL;
8334    Eina_List *nl = NULL;
8335    E_Border *bd = NULL;
8336    E_Border_Rotation_Info *info = NULL;
8337
8338    if (!e_config->wm_win_rotation) return EINA_FALSE;
8339
8340    l = e_container_border_list_last(zone->container);
8341    if (!l) return EINA_FALSE;
8342    while ((bd = e_container_border_list_prev(l)))
8343      {
8344         if ((!bd) || (e_object_is_del(E_OBJECT(bd)))) continue;
8345
8346         if ((without_vkbd) &&
8347             (((rot.vkbd) && (rot.vkbd == bd)) ||
8348              ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))) continue;
8349
8350         if ((bd->visible) &&
8351             ((bd->client.e.state.rot.support) || (bd->client.e.state.rot.app_set)) &&
8352             (bd->zone == zone) &&
8353             (E_INTERSECTS(zone->x, zone->y, zone->w, zone->h,
8354                           bd->x, bd->y, bd->w, bd->h)))
8355           {
8356              // check if this window is available to be rotate.
8357              if ((bd->client.e.state.rot.app_set) &&
8358                  (bd->client.e.state.rot.preferred_rot != -1)) continue;
8359
8360              /* check list of available rotations */
8361              int ang = zone->rot.curr;
8362              if (bd->client.e.state.rot.app_set)
8363                {
8364                   ang = _e_border_rotation_get(bd, ang);
8365                   ELBF(ELBT_ROT, 0, bd->client.win, "returned ang:%d", ang);
8366                }
8367
8368              /* skip same angle */
8369              if (bd->client.e.state.rot.curr == ang)
8370                {
8371                   ELBF(ELBT_ROT, 0, bd->client.win, "SKIP ang:%d", ang);
8372                   continue;
8373                }
8374              else
8375                {
8376                   ELBF(ELBT_ROT, 0, bd->client.win, "ADD ROT_LIST curr:%d != ang:%d",
8377                        bd->client.e.state.rot.curr, ang);
8378                }
8379
8380              bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8381              bd->client.e.state.rot.curr = ang;
8382              bd->client.e.state.rot.wait_for_done = 1;
8383
8384              info = E_NEW(E_Border_Rotation_Info, 1);
8385              if (info)
8386                {
8387                   info->bd = bd;
8388                   info->ang = ang;
8389                   info->x = bd->x; info->y = bd->y;
8390                   info->w = bd->w; info->h = bd->h;
8391                   info->win_resize = EINA_FALSE;
8392                   nl = eina_list_append(nl, info);
8393                }
8394
8395              if (REGION_EQUAL_TO_ZONE(bd, zone))
8396                {
8397                   wait = EINA_TRUE; // for the maximized window
8398                }
8399              else
8400                {
8401                   int diff = bd->client.e.state.rot.curr - bd->client.e.state.rot.prev;
8402                   int x, y, w, h;
8403                   Eina_Bool resize = EINA_TRUE;
8404                   if ((diff == 180) || (diff == -180))
8405                     resize = EINA_FALSE;
8406
8407                   Eina_Bool move = EINA_TRUE;
8408                   Eina_Bool hint = EINA_FALSE;
8409                   hint = _e_border_rotation_geom_get(bd, zone, zone->rot.curr, &x, &y, &w, &h, &move);
8410                   if (hint)
8411                     _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
8412                   else
8413                     {
8414                        x = bd->x; y = bd->y;
8415                        w = bd->w; h = bd->h;
8416                        if (resize)
8417                          {
8418                             if (w == h)
8419                               resize = EINA_FALSE;
8420                             else
8421                               {
8422                                  // swap width and height and resize border
8423                                  w = bd->h;
8424                                  h = bd->w;
8425
8426                                  _e_border_move_resize_internal(bd, x, y, w, h,
8427                                                                 EINA_TRUE, EINA_TRUE);
8428                               }
8429                          }
8430                     }
8431
8432                   if (info)
8433                     {
8434                        info->x = x; info->y = y;
8435                        info->w = w; info->h = h;
8436                        info->win_resize = resize;
8437                     }
8438
8439                   if (resize)
8440                     bd->client.e.state.rot.pending_change_request = 1;
8441
8442                   wait = EINA_TRUE;
8443                }
8444
8445              /* support for rotating prediction window without virtual keyboard */
8446              if (without_vkbd)
8447                {
8448                   if ((rot.vkbd != bd) && (rot.vkbd_prediction != bd) &&
8449                       /* check whether prediction is visible on the zone */
8450                       (_e_border_rotation_zone_prediction_check(bd->zone)) &&
8451                       /* check whether prediction window belongs to this border (transient_for) */
8452                       (rot.vkbd_prediction->parent == bd) &&
8453                       /* check rotation of prediction window */
8454                       (rot.vkbd_prediction->client.e.state.rot.curr != bd->client.e.state.rot.curr) &&
8455                       (!rot.wait_prepare_done))
8456                     {
8457                        E_Border *pbd = rot.vkbd_prediction;
8458                        ang = bd->client.e.state.rot.curr;
8459
8460                        ELBF(ELBT_ROT, 0, pbd->client.win, "ADD ROT_LIST curr:%d != ang:%d (PREDICTION)",
8461                             pbd->client.e.state.rot.curr, ang);
8462
8463                        pbd->client.e.state.rot.prev = pbd->client.e.state.rot.curr;
8464                        pbd->client.e.state.rot.curr = ang;
8465                        pbd->client.e.state.rot.wait_for_done = 1;
8466
8467                        info = E_NEW(E_Border_Rotation_Info, 1);
8468                        if (info)
8469                          {
8470                             info->bd = pbd;
8471                             info->ang = ang;
8472                             info->x = pbd->x; info->y = pbd->y;
8473                             info->w = pbd->w; info->h = pbd->h;
8474                             info->win_resize = EINA_FALSE;
8475                             nl = eina_list_append(nl, info);
8476                          }
8477
8478                        int x, y, w, h;
8479                        Eina_Bool move = EINA_TRUE;
8480                        Eina_Bool hint = EINA_FALSE;
8481                        hint = _e_border_rotation_geom_get(pbd, zone, zone->rot.curr, &x, &y, &w, &h, &move);
8482                        if (hint)
8483                          _e_border_move_resize_internal(pbd, x, y, w, h, EINA_TRUE, move);
8484
8485                        if (info)
8486                          {
8487                             info->x = x; info->y = y;
8488                             info->w = w; info->h = h;
8489                             info->win_resize = EINA_TRUE;
8490                          }
8491
8492                        pbd->client.e.state.rot.pending_change_request = 1;
8493                     }
8494                }
8495           }
8496      }
8497
8498    if (l) e_container_border_list_free(l);
8499
8500    if (nl)
8501      {
8502         // clear previous list
8503         EINA_LIST_FREE(rot.list, info)
8504           {
8505              E_FREE(info);
8506           }
8507         rot.list = nl;
8508      }
8509
8510    return wait;
8511 }
8512
8513 static Eina_Bool
8514 _e_border_cb_window_configure(void *data    __UNUSED__,
8515                               int   ev_type __UNUSED__,
8516                               void         *ev)
8517 {
8518    Ecore_X_Event_Window_Configure *e = ev;
8519    if (!e) return ECORE_CALLBACK_PASS_ON;
8520    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8521
8522    E_Border *bd = e_border_find_by_client_window(e->win);
8523    if (!bd) return ECORE_CALLBACK_PASS_ON;
8524
8525    if (bd->client.e.state.rot.pending_change_request)
8526      {
8527         if ((e->w == bd->w) && (e->h == bd->h))
8528           {
8529              ELBF(ELBT_ROT, 0, bd->client.win,
8530                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
8531                   bd->client.e.state.rot.curr,
8532                   bd->w, bd->h);
8533
8534              bd->client.e.state.rot.pending_change_request = 0;
8535
8536              ecore_x_e_window_rotation_change_request_send(bd->client.win,
8537                                                            bd->client.e.state.rot.curr);
8538           }
8539      }
8540    return ECORE_CALLBACK_PASS_ON;
8541 }
8542
8543 static Eina_Bool
8544 _e_border_rotation_geom_get(E_Border  *bd,
8545                             E_Zone    *zone,
8546                             int        ang,
8547                             int       *x,
8548                             int       *y,
8549                             int       *w,
8550                             int       *h,
8551                             Eina_Bool *move)
8552 {
8553    if (!e_config->wm_win_rotation) return EINA_FALSE;
8554
8555    Eina_Bool res = EINA_FALSE;
8556    Eina_Bool _move = EINA_TRUE;
8557    int _x = bd->x;
8558    int _y = bd->y;
8559    int _w = bd->w;
8560    int _h = bd->h;
8561
8562    if (x) *x = bd->x;
8563    if (y) *y = bd->y;
8564    if (w) *w = bd->w;
8565    if (h) *h = bd->h;
8566    if (move) *move = EINA_TRUE;
8567
8568    if (bd->client.e.state.rot.geom_hint)
8569      {
8570         switch (ang)
8571           {
8572            case   0:
8573               _w = bd->client.e.state.rot.geom[0].w;
8574               _h = bd->client.e.state.rot.geom[0].h;
8575               if (_w == 0) _w = bd->w;
8576               if (_h == 0) _h = bd->h;
8577               _x = 0; _y = zone->h - _h;
8578               break;
8579            case  90:
8580               _w = bd->client.e.state.rot.geom[1].w;
8581               _h = bd->client.e.state.rot.geom[1].h;
8582               if (_w == 0) _w = bd->w;
8583               if (_h == 0) _h = bd->h;
8584               _x = zone->w - _w; _y = 0;
8585               break;
8586            case 180:
8587               _w = bd->client.e.state.rot.geom[2].w;
8588               _h = bd->client.e.state.rot.geom[2].h;
8589               if (_w == 0) _w = bd->w;
8590               if (_h == 0) _h = bd->h;
8591               _x = 0; _y = 0;
8592               break;
8593            case 270:
8594               _w = bd->client.e.state.rot.geom[3].w;
8595               _h = bd->client.e.state.rot.geom[3].h;
8596               if (_w == 0) _w = bd->w;
8597               if (_h == 0) _h = bd->h;
8598               _x = 0; _y = 0;
8599               break;
8600           }
8601
8602         if (x) *x = _x;
8603         if (y) *y = _y;
8604         if (w) *w = _w;
8605         if (h) *h = _h;
8606
8607         if (!((rot.vkbd) && (rot.vkbd == bd)))
8608           {
8609              if (x) *x = bd->x;
8610              if (y) *y = bd->y;
8611              if (move) *move = EINA_FALSE;
8612           }
8613
8614         res = EINA_TRUE;
8615      }
8616
8617    if (res)
8618      {
8619         _x = 0; _y = 0; _w = 0; _h = 0;
8620         if (x) _x = *x;
8621         if (y) _y = *y;
8622         if (w) _w = *w;
8623         if (h) _h = *h;
8624         if (move) _move = *move;
8625
8626         ELBF(ELBT_ROT, 1, bd->client.win,
8627              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
8628              ang, _x, _y, _w, _h, _move);
8629      }
8630
8631    return res;
8632 }
8633 #endif
8634
8635 static Eina_Bool
8636 _e_border_post_move_resize_job(void *data)
8637 {
8638    E_Border *bd;
8639
8640    bd = (E_Border *)data;
8641    if (bd->post_move)
8642      {
8643         E_Border *tmp;
8644         Eina_List *l;
8645
8646         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
8647           ecore_x_window_move(tmp->win,
8648                               bd->x +
8649                               bd->client_inset.l +
8650                               bd->fx.x +
8651                               tmp->client.e.state.video_position.x,
8652                               bd->y +
8653                               bd->client_inset.t +
8654                               bd->fx.y +
8655                               tmp->client.e.state.video_position.y);
8656      }
8657    if (bd->client.e.state.video)
8658      {
8659         E_Border *parent;
8660
8661         parent = bd->client.e.state.video_parent_border;
8662         ecore_x_window_move(bd->win,
8663                             parent->x +
8664                             parent->client_inset.l +
8665                             parent->fx.x +
8666                             bd->client.e.state.video_position.x,
8667                             parent->y +
8668                             parent->client_inset.t +
8669                             parent->fx.y +
8670                             bd->client.e.state.video_position.y);
8671      }
8672    else if ((bd->post_move) && (bd->post_resize))
8673      {
8674         ecore_x_window_move_resize(bd->win,
8675                                    bd->x + bd->fx.x,
8676                                    bd->y + bd->fx.y,
8677                                    bd->w, bd->h);
8678      }
8679    else if (bd->post_move)
8680      {
8681         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
8682      }
8683    else if (bd->post_resize)
8684      {
8685         ecore_x_window_resize(bd->win, bd->w, bd->h);
8686      }
8687
8688    if (bd->client.e.state.video)
8689      {
8690         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
8691                 bd->win,
8692                 bd->client.e.state.video_parent_border->x +
8693                 bd->client.e.state.video_parent_border->client_inset.l +
8694                 bd->client.e.state.video_parent_border->fx.x +
8695                 bd->client.e.state.video_position.x,
8696                 bd->client.e.state.video_parent_border->y +
8697                 bd->client.e.state.video_parent_border->client_inset.t +
8698                 bd->client.e.state.video_parent_border->fx.y +
8699                 bd->client.e.state.video_position.y,
8700                 bd->w, bd->h);
8701      }
8702
8703    if (bd->post_show)
8704      {
8705         if (bd->visible)
8706           {
8707              bd->post_job = NULL;
8708              _e_border_show(bd);
8709           }
8710      }
8711    bd->post_show = 0;
8712    bd->post_move = 0;
8713    bd->post_resize = 0;
8714    bd->post_job = NULL;
8715    return ECORE_CALLBACK_CANCEL;
8716 }
8717
8718 static void
8719 _e_border_container_layout_hook(E_Container *con)
8720 {
8721    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
8722 }
8723
8724 static void
8725 _e_border_eval0(E_Border *bd)
8726 {
8727    int change_urgent = 0;
8728    int rem_change = 0;
8729 #ifdef _F_USE_DESK_WINDOW_PROFILE_
8730    Eina_Bool need_desk_set = EINA_FALSE;
8731 #endif
8732 #ifdef _F_ZONE_WINDOW_ROTATION_
8733    Eina_Bool need_rotation_set = EINA_FALSE;
8734
8735    if ((e_config->wm_win_rotation) &&
8736        (bd->client.icccm.fetch.transient_for))
8737      {
8738         if (((rot.vkbd) && (rot.vkbd == bd)) ||
8739             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
8740           {
8741              need_rotation_set = EINA_TRUE;
8742              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
8743           }
8744      }
8745 #endif
8746
8747    if (e_object_is_del(E_OBJECT(bd)))
8748      {
8749         CRI("_e_border_eval(%p) with deleted border!\n", bd);
8750         bd->changed = 0;
8751         return;
8752      }
8753
8754    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
8755
8756    bd->changes.border = 0;
8757
8758    /* fetch any info queued to be fetched */
8759    if (bd->client.netwm.fetch.state)
8760      {
8761         e_hints_window_state_get(bd);
8762         bd->client.netwm.fetch.state = 0;
8763         rem_change = 1;
8764      }
8765    if (bd->client.icccm.fetch.client_leader)
8766      {
8767         /* TODO: What do to if the client leader isn't mapped yet? */
8768         E_Border *bd_leader = NULL;
8769
8770         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
8771         if (bd->client.icccm.client_leader)
8772           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
8773         if (bd->leader)
8774           {
8775              if (bd->leader != bd_leader)
8776                {
8777                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
8778                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
8779                   bd->leader = NULL;
8780                }
8781              else
8782                bd_leader = NULL;
8783           }
8784         /* If this border is the leader of the group, don't register itself */
8785         if ((bd_leader) && (bd_leader != bd))
8786           {
8787              bd_leader->group = eina_list_append(bd_leader->group, bd);
8788              bd->leader = bd_leader;
8789              /* Only set the window modal to the leader it there is no parent */
8790              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
8791                  ((!bd->parent) || (bd->parent->modal != bd)))
8792                {
8793                   bd->leader->modal = bd;
8794                   if (bd->leader->focused)
8795                     e_border_focus_set(bd, 1, 1);
8796                   else
8797                     {
8798                        Eina_List *l;
8799                        E_Border *child;
8800
8801                        EINA_LIST_FOREACH(bd->leader->group, l, child)
8802                          {
8803                             if ((child != bd) && (child->focused))
8804                               e_border_focus_set(bd, 1, 1);
8805                          }
8806                     }
8807                }
8808           }
8809         bd->client.icccm.fetch.client_leader = 0;
8810         rem_change = 1;
8811      }
8812    if (bd->client.icccm.fetch.title)
8813      {
8814         char *title = ecore_x_icccm_title_get(bd->client.win);
8815         eina_stringshare_replace(&bd->client.icccm.title, title);
8816         if (title) free(title);
8817
8818         if (bd->bg_object)
8819           edje_object_part_text_set(bd->bg_object, "e.text.title",
8820                                     bd->client.icccm.title);
8821         bd->client.icccm.fetch.title = 0;
8822         rem_change = 1;
8823      }
8824    if (bd->client.netwm.fetch.name)
8825      {
8826         char *name;
8827         ecore_x_netwm_name_get(bd->client.win, &name);
8828         eina_stringshare_replace(&bd->client.netwm.name, name);
8829         if (name) free(name);
8830
8831         if (bd->bg_object)
8832           edje_object_part_text_set(bd->bg_object, "e.text.title",
8833                                     bd->client.netwm.name);
8834         bd->client.netwm.fetch.name = 0;
8835         rem_change = 1;
8836      }
8837    if (bd->client.icccm.fetch.name_class)
8838      {
8839         const char *pname, *pclass;
8840         char *nname, *nclass;
8841
8842         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
8843         pname = bd->client.icccm.name;
8844         pclass = bd->client.icccm.class;
8845         bd->client.icccm.name = eina_stringshare_add(nname);
8846         bd->client.icccm.class = eina_stringshare_add(nclass);
8847         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
8848           e_bindings_mapping_change_enable(EINA_FALSE);
8849 #ifdef _F_ZONE_WINDOW_ROTATION_
8850         if (e_config->wm_win_rotation)
8851           {
8852              if ((bd->client.icccm.name) && (bd->client.icccm.class))
8853                {
8854                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
8855                       (!strcmp(bd->client.icccm.class, "ISF")))
8856                     {
8857                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
8858                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
8859                        rot.vkbd = bd;
8860                     }
8861                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
8862                            (!strcmp(bd->client.icccm.class, "ISF")))
8863                     {
8864                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
8865                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
8866                        rot.vkbd_prediction = bd;
8867                     }
8868                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
8869                            (!strcmp(bd->client.icccm.class, "ISF")))
8870                     {
8871                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
8872                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
8873                     }
8874                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
8875                            (!strcmp(bd->client.icccm.class, "ISF")))
8876                     {
8877                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
8878                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
8879                     }
8880                }
8881           }
8882 #endif
8883         if (nname) free(nname);
8884         if (nclass) free(nclass);
8885
8886         if (!((bd->client.icccm.name == pname) &&
8887               (bd->client.icccm.class == pclass)))
8888           bd->changes.icon = 1;
8889
8890         if (pname) eina_stringshare_del(pname);
8891         if (pclass) eina_stringshare_del(pclass);
8892         bd->client.icccm.fetch.name_class = 0;
8893         bd->changes.icon = 1;
8894         rem_change = 1;
8895      }
8896    if (bd->client.icccm.fetch.state)
8897      {
8898         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
8899         bd->client.icccm.fetch.state = 0;
8900         rem_change = 1;
8901      }
8902    if (bd->client.e.fetch.state)
8903      {
8904         e_hints_window_e_state_get(bd);
8905         bd->client.e.fetch.state = 0;
8906         rem_change = 1;
8907      }
8908 #ifdef _F_USE_DESK_WINDOW_PROFILE_
8909    if (bd->client.e.fetch.profile_list)
8910      {
8911         const char **profiles = NULL;
8912         const char *str;
8913         int num, i;
8914
8915         if (bd->client.e.state.profile)
8916           eina_stringshare_del(bd->client.e.state.profile);
8917         EINA_LIST_FREE(bd->client.e.state.profiles, str)
8918           {
8919              if (str) eina_stringshare_del(str);
8920           }
8921         bd->client.e.state.profile = NULL;
8922         bd->client.e.state.profiles = NULL;
8923         bd->client.e.state.profile_list = 0;
8924
8925         if (ecore_x_e_window_profile_list_get(bd->client.win,
8926                                               &profiles, &num))
8927           {
8928              bd->client.e.state.profile_list = 1;
8929              for (i = 0; i < num; i++)
8930                {
8931                   str = eina_stringshare_add(profiles[i]);
8932                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
8933                }
8934
8935              /* We should set desk to contain given border after creating E_BORDER_ADD event.
8936               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
8937               */
8938              need_desk_set = EINA_TRUE;
8939           }
8940         else
8941           {
8942              if (strcmp(bd->desk->window_profile,
8943                         e_config->desktop_default_window_profile) != 0)
8944                {
8945                   ecore_x_e_window_profile_set(bd->client.win,
8946                                                bd->desk->window_profile);
8947                }
8948           }
8949
8950         if (profiles)
8951           free(profiles);
8952
8953         bd->client.e.fetch.profile_list = 0;
8954      }
8955 #endif
8956 #ifdef _F_ZONE_WINDOW_ROTATION_
8957    if ((e_config->wm_win_rotation) &&
8958        (bd->client.e.fetch.rot.support))
8959      {
8960         int ret = 0;
8961         unsigned int support = 0;
8962
8963         ret = ecore_x_window_prop_card32_get
8964           (bd->client.win,
8965           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
8966           &support, 1);
8967
8968         bd->client.e.state.rot.support = 0;
8969         if ((ret == 1) && (support == 1))
8970           bd->client.e.state.rot.support = 1;
8971
8972         if (bd->client.e.state.rot.support)
8973           need_rotation_set = EINA_TRUE;
8974
8975         bd->client.e.fetch.rot.support = 0;
8976      }
8977    if ((e_config->wm_win_rotation) &&
8978        (bd->client.e.fetch.rot.geom_hint))
8979      {
8980         Eina_Rectangle r[4];
8981         int i, x, y, w, h;
8982         bd->client.e.state.rot.geom_hint = 0;
8983         for (i = 0; i < 4; i++)
8984           {
8985              r[i].x = bd->client.e.state.rot.geom[i].x;
8986              r[i].y = bd->client.e.state.rot.geom[i].y;
8987              r[i].w = bd->client.e.state.rot.geom[i].w;
8988              r[i].h = bd->client.e.state.rot.geom[i].h;
8989
8990              bd->client.e.state.rot.geom[i].x = 0;
8991              bd->client.e.state.rot.geom[i].y = 0;
8992              bd->client.e.state.rot.geom[i].w = 0;
8993              bd->client.e.state.rot.geom[i].h = 0;
8994           }
8995
8996         for (i = 0; i < 4; i++)
8997           {
8998              x = 0; y = 0; w = 0; h = 0;
8999              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
9000                {
9001                   bd->client.e.state.rot.geom_hint = 1;
9002                   bd->client.e.state.rot.geom[i].x = x;
9003                   bd->client.e.state.rot.geom[i].y = y;
9004                   bd->client.e.state.rot.geom[i].w = w;
9005                   bd->client.e.state.rot.geom[i].h = h;
9006
9007                   if (!((r[i].x == x) && (r[i].y == y) &&
9008                         (r[i].w == w) && (r[i].h == h)))
9009                     {
9010                        need_rotation_set = EINA_TRUE;
9011                     }
9012                }
9013           }
9014         bd->client.e.fetch.rot.geom_hint = 0;
9015      }
9016    if ((e_config->wm_win_rotation) &&
9017        (bd->client.e.fetch.rot.app_set))
9018      {
9019         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
9020         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
9021         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
9022
9023         if (_prev_app_set != bd->client.e.state.rot.app_set)
9024           need_rotation_set = EINA_TRUE;
9025
9026         bd->client.e.fetch.rot.app_set = 0;
9027      }
9028    if ((e_config->wm_win_rotation) &&
9029        (bd->client.e.fetch.rot.preferred_rot))
9030      {
9031         int r = 0, _prev_preferred_rot;
9032         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
9033         bd->client.e.state.rot.preferred_rot = -1;
9034         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
9035           {
9036              bd->client.e.state.rot.preferred_rot = r;
9037              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
9038           }
9039         else
9040           {
9041              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
9042           }
9043
9044         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
9045           need_rotation_set = EINA_TRUE;
9046
9047         bd->client.e.fetch.rot.preferred_rot = 0;
9048      }
9049    if ((e_config->wm_win_rotation) &&
9050        (bd->client.e.fetch.rot.available_rots))
9051      {
9052         Eina_Bool res, diff = EINA_FALSE;
9053         int *rots = NULL;
9054         unsigned int count = 0, i = 0;
9055         int _prev_rots[4] = { -1, };
9056
9057         if (bd->client.e.state.rot.available_rots)
9058           {
9059              memcpy(_prev_rots,
9060                     bd->client.e.state.rot.available_rots,
9061                     (sizeof(int) * bd->client.e.state.rot.count));
9062
9063              E_FREE(bd->client.e.state.rot.available_rots);
9064           }
9065
9066         bd->client.e.state.rot.count = 0;
9067
9068         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
9069                                                                 &rots, &count);
9070         if ((res) && (count > 0) && (rots))
9071           {
9072              bd->client.e.state.rot.available_rots = rots;
9073              bd->client.e.state.rot.count = count;
9074
9075              for (i = 0; i < count; i++)
9076                {
9077                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
9078                   if ((!diff) && (_prev_rots[i] != rots[i]))
9079                     {
9080                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
9081                             count, i, _prev_rots[i], rots[i]);
9082                        diff = EINA_TRUE;
9083                     }
9084                }
9085           }
9086         else
9087           {
9088              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9089              diff = EINA_TRUE;
9090           }
9091
9092         if (diff) need_rotation_set = EINA_TRUE;
9093         bd->client.e.fetch.rot.available_rots = 0;
9094      }
9095 #endif
9096    if (bd->client.netwm.fetch.type)
9097      {
9098         e_hints_window_type_get(bd);
9099         if ((!bd->lock_border) || (!bd->client.border.name))
9100           bd->client.border.changed = 1;
9101
9102         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9103           {
9104              if (!bd->client.netwm.state.skip_pager)
9105                {
9106                   bd->client.netwm.state.skip_pager = 1;
9107                   bd->client.netwm.update.state = 1;
9108                }
9109              if (!bd->client.netwm.state.skip_taskbar)
9110                {
9111                   bd->client.netwm.state.skip_taskbar = 1;
9112                   bd->client.netwm.update.state = 1;
9113                }
9114           }
9115         bd->client.netwm.fetch.type = 0;
9116      }
9117    if (bd->client.icccm.fetch.machine)
9118      {
9119         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9120
9121         if ((!machine) && (bd->client.icccm.client_leader))
9122           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9123
9124         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9125         if (machine) free(machine);
9126
9127         bd->client.icccm.fetch.machine = 0;
9128         rem_change = 1;
9129      }
9130    if (bd->client.icccm.fetch.command)
9131      {
9132         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9133           {
9134              int i;
9135
9136              for (i = 0; i < bd->client.icccm.command.argc; i++)
9137                free(bd->client.icccm.command.argv[i]);
9138              free(bd->client.icccm.command.argv);
9139           }
9140         bd->client.icccm.command.argc = 0;
9141         bd->client.icccm.command.argv = NULL;
9142         ecore_x_icccm_command_get(bd->client.win,
9143                                   &(bd->client.icccm.command.argc),
9144                                   &(bd->client.icccm.command.argv));
9145         if ((bd->client.icccm.client_leader) &&
9146             (!bd->client.icccm.command.argv))
9147           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9148                                     &(bd->client.icccm.command.argc),
9149                                     &(bd->client.icccm.command.argv));
9150         bd->client.icccm.fetch.command = 0;
9151         rem_change = 1;
9152      }
9153    if (bd->client.icccm.fetch.hints)
9154      {
9155         Eina_Bool accepts_focus, is_urgent;
9156
9157         accepts_focus = EINA_TRUE;
9158         is_urgent = EINA_FALSE;
9159         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9160         if (ecore_x_icccm_hints_get(bd->client.win,
9161                                     &accepts_focus,
9162                                     &bd->client.icccm.initial_state,
9163                                     &bd->client.icccm.icon_pixmap,
9164                                     &bd->client.icccm.icon_mask,
9165                                     &bd->client.icccm.icon_window,
9166                                     &bd->client.icccm.window_group,
9167                                     &is_urgent))
9168           {
9169              bd->client.icccm.accepts_focus = accepts_focus;
9170              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9171                change_urgent = 1;
9172              bd->client.icccm.urgent = is_urgent;
9173
9174              /* If this is a new window, set the state as requested. */
9175              if ((bd->new_client) &&
9176                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9177                {
9178                   e_border_iconify(bd);
9179                   e_border_hide(bd, 1);
9180                }
9181           }
9182         bd->client.icccm.fetch.hints = 0;
9183         rem_change = 1;
9184      }
9185    if (bd->client.icccm.fetch.size_pos_hints)
9186      {
9187         Eina_Bool request_pos;
9188
9189         request_pos = EINA_FALSE;
9190         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9191                                              &request_pos,
9192                                              &bd->client.icccm.gravity,
9193                                              &bd->client.icccm.min_w,
9194                                              &bd->client.icccm.min_h,
9195                                              &bd->client.icccm.max_w,
9196                                              &bd->client.icccm.max_h,
9197                                              &bd->client.icccm.base_w,
9198                                              &bd->client.icccm.base_h,
9199                                              &bd->client.icccm.step_w,
9200                                              &bd->client.icccm.step_h,
9201                                              &bd->client.icccm.min_aspect,
9202                                              &bd->client.icccm.max_aspect))
9203           {
9204              bd->client.icccm.request_pos = request_pos;
9205           }
9206         else
9207           {
9208           }
9209         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9210         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9211         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9212         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9213         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9214         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9215         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9216         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9217         // if doing a resize, fix it up
9218         if (bd->resize_mode != RESIZE_NONE)
9219           {
9220              int x, y, w, h, new_w, new_h;
9221
9222              x = bd->x;
9223              y = bd->y;
9224              w = bd->w;
9225              h = bd->h;
9226              new_w = w;
9227              new_h = h;
9228              e_border_resize_limit(bd, &new_w, &new_h);
9229              if ((bd->resize_mode == RESIZE_TL) ||
9230                  (bd->resize_mode == RESIZE_L) ||
9231                  (bd->resize_mode == RESIZE_BL))
9232                x += (w - new_w);
9233              if ((bd->resize_mode == RESIZE_TL) ||
9234                  (bd->resize_mode == RESIZE_T) ||
9235                  (bd->resize_mode == RESIZE_TR))
9236                y += (h - new_h);
9237              e_border_move_resize(bd, x, y, new_w, new_h);
9238           }
9239         bd->client.icccm.fetch.size_pos_hints = 0;
9240         rem_change = 1;
9241      }
9242    if (bd->client.icccm.fetch.protocol)
9243      {
9244         int i, num;
9245         Ecore_X_WM_Protocol *proto;
9246
9247         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9248         if (proto)
9249           {
9250              for (i = 0; i < num; i++)
9251                {
9252                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9253                     bd->client.icccm.delete_request = 1;
9254                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9255                     bd->client.icccm.take_focus = 1;
9256                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9257                     bd->client.netwm.ping = 1;
9258                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9259                     {
9260                        bd->client.netwm.sync.request = 1;
9261                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9262                                                            &bd->client.netwm.sync.counter))
9263                          bd->client.netwm.sync.request = 0;
9264                     }
9265                }
9266              free(proto);
9267           }
9268         if (bd->client.netwm.ping)
9269           e_border_ping(bd);
9270         else
9271           {
9272              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9273              bd->ping_poller = NULL;
9274           }
9275         bd->client.icccm.fetch.protocol = 0;
9276      }
9277    if (bd->client.icccm.fetch.transient_for)
9278      {
9279         /* TODO: What do to if the transient for isn't mapped yet? */
9280         E_Border *bd_parent = NULL;
9281
9282         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9283         if (bd->client.icccm.transient_for)
9284           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9285         /* If we already have a parent, remove it */
9286         if (bd->parent)
9287           {
9288              if (bd_parent != bd->parent)
9289                {
9290                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9291                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9292                   bd->parent = NULL;
9293                }
9294              else
9295                bd_parent = NULL;
9296           }
9297         if ((bd_parent) && (bd_parent != bd) &&
9298             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9299           {
9300              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9301              bd->parent = bd_parent;
9302           }
9303         if (bd->parent)
9304           {
9305              e_border_layer_set(bd, bd->parent->layer);
9306              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9307                {
9308                   Ecore_X_Window_Attributes attr;
9309                   bd->parent->modal = bd;
9310                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9311                   bd->parent->saved.event_mask = attr.event_mask.mine;
9312                   bd->parent->lock_close = 1;
9313                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9314                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9315                }
9316
9317              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9318                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9319                bd->take_focus = 1;
9320           }
9321         bd->client.icccm.fetch.transient_for = 0;
9322         rem_change = 1;
9323      }
9324    if (bd->client.icccm.fetch.window_role)
9325      {
9326         char *role = ecore_x_icccm_window_role_get(bd->client.win);
9327         eina_stringshare_replace(&bd->client.icccm.window_role, role);
9328         if (role) free(role);
9329
9330         bd->client.icccm.fetch.window_role = 0;
9331         rem_change = 1;
9332      }
9333    if (bd->client.icccm.fetch.icon_name)
9334      {
9335         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
9336         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
9337         if (icon_name) free(icon_name);
9338
9339         bd->client.icccm.fetch.icon_name = 0;
9340         rem_change = 1;
9341      }
9342    if (bd->client.netwm.fetch.icon_name)
9343      {
9344         char *icon_name;
9345         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
9346         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
9347         if (icon_name) free(icon_name);
9348
9349         bd->client.netwm.fetch.icon_name = 0;
9350         rem_change = 1;
9351      }
9352    if (bd->client.netwm.fetch.icon)
9353      {
9354         int i;
9355         if (bd->client.netwm.icons)
9356           {
9357              for (i = 0; i < bd->client.netwm.num_icons; i++)
9358                {
9359                   free(bd->client.netwm.icons[i].data);
9360                   bd->client.netwm.icons[i].data = NULL;
9361                }
9362              free(bd->client.netwm.icons);
9363           }
9364         bd->client.netwm.icons = NULL;
9365         bd->client.netwm.num_icons = 0;
9366         if (ecore_x_netwm_icons_get(bd->client.win,
9367                                      &bd->client.netwm.icons,
9368                                      &bd->client.netwm.num_icons))
9369           {
9370              // unless the rest of e17 uses border icons OTHER than icon #0
9371              // then free the rest that we don't need anymore.
9372              for (i = 1; i < bd->client.netwm.num_icons; i++)
9373                {
9374                   free(bd->client.netwm.icons[i].data);
9375                   bd->client.netwm.icons[i].data = NULL;
9376                }
9377              bd->client.netwm.num_icons = 1;
9378              bd->changes.icon = 1;
9379           }
9380         bd->client.netwm.fetch.icon = 0;
9381      }
9382    if (bd->client.netwm.fetch.user_time)
9383      {
9384         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
9385         bd->client.netwm.fetch.user_time = 0;
9386      }
9387    if (bd->client.netwm.fetch.strut)
9388      {
9389         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
9390                                              &bd->client.netwm.strut.left,
9391                                              &bd->client.netwm.strut.right,
9392                                              &bd->client.netwm.strut.top,
9393                                              &bd->client.netwm.strut.bottom,
9394                                              &bd->client.netwm.strut.left_start_y,
9395                                              &bd->client.netwm.strut.left_end_y,
9396                                              &bd->client.netwm.strut.right_start_y,
9397                                              &bd->client.netwm.strut.right_end_y,
9398                                              &bd->client.netwm.strut.top_start_x,
9399                                              &bd->client.netwm.strut.top_end_x,
9400                                              &bd->client.netwm.strut.bottom_start_x,
9401                                              &bd->client.netwm.strut.bottom_end_x))
9402           {
9403              ecore_x_netwm_strut_get(bd->client.win,
9404                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
9405                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
9406
9407              bd->client.netwm.strut.left_start_y = 0;
9408              bd->client.netwm.strut.left_end_y = 0;
9409              bd->client.netwm.strut.right_start_y = 0;
9410              bd->client.netwm.strut.right_end_y = 0;
9411              bd->client.netwm.strut.top_start_x = 0;
9412              bd->client.netwm.strut.top_end_x = 0;
9413              bd->client.netwm.strut.bottom_start_x = 0;
9414              bd->client.netwm.strut.bottom_end_x = 0;
9415           }
9416         bd->client.netwm.fetch.strut = 0;
9417      }
9418    if (bd->client.qtopia.fetch.soft_menu)
9419      {
9420         e_hints_window_qtopia_soft_menu_get(bd);
9421         bd->client.qtopia.fetch.soft_menu = 0;
9422         rem_change = 1;
9423      }
9424    if (bd->client.qtopia.fetch.soft_menus)
9425      {
9426         e_hints_window_qtopia_soft_menus_get(bd);
9427         bd->client.qtopia.fetch.soft_menus = 0;
9428         rem_change = 1;
9429      }
9430    if (bd->client.vkbd.fetch.state)
9431      {
9432         e_hints_window_virtual_keyboard_state_get(bd);
9433         bd->client.vkbd.fetch.state = 0;
9434         rem_change = 1;
9435      }
9436    if (bd->client.vkbd.fetch.vkbd)
9437      {
9438         e_hints_window_virtual_keyboard_get(bd);
9439         bd->client.vkbd.fetch.vkbd = 0;
9440         rem_change = 1;
9441      }
9442    if (bd->client.illume.conformant.fetch.conformant)
9443      {
9444         bd->client.illume.conformant.conformant =
9445           ecore_x_e_illume_conformant_get(bd->client.win);
9446         bd->client.illume.conformant.fetch.conformant = 0;
9447      }
9448    if (bd->client.illume.quickpanel.fetch.state)
9449      {
9450         bd->client.illume.quickpanel.state =
9451           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
9452         bd->client.illume.quickpanel.fetch.state = 0;
9453      }
9454    if (bd->client.illume.quickpanel.fetch.quickpanel)
9455      {
9456         bd->client.illume.quickpanel.quickpanel =
9457           ecore_x_e_illume_quickpanel_get(bd->client.win);
9458         bd->client.illume.quickpanel.fetch.quickpanel = 0;
9459      }
9460    if (bd->client.illume.quickpanel.fetch.priority.major)
9461      {
9462         bd->client.illume.quickpanel.priority.major =
9463           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
9464         bd->client.illume.quickpanel.fetch.priority.major = 0;
9465      }
9466    if (bd->client.illume.quickpanel.fetch.priority.minor)
9467      {
9468         bd->client.illume.quickpanel.priority.minor =
9469           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
9470         bd->client.illume.quickpanel.fetch.priority.minor = 0;
9471      }
9472    if (bd->client.illume.quickpanel.fetch.zone)
9473      {
9474         bd->client.illume.quickpanel.zone =
9475           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
9476         bd->client.illume.quickpanel.fetch.zone = 0;
9477      }
9478    if (bd->client.illume.drag.fetch.drag)
9479      {
9480         bd->client.illume.drag.drag =
9481           ecore_x_e_illume_drag_get(bd->client.win);
9482         bd->client.illume.drag.fetch.drag = 0;
9483      }
9484    if (bd->client.illume.drag.fetch.locked)
9485      {
9486         bd->client.illume.drag.locked =
9487           ecore_x_e_illume_drag_locked_get(bd->client.win);
9488         bd->client.illume.drag.fetch.locked = 0;
9489      }
9490    if (bd->client.illume.win_state.fetch.state)
9491      {
9492         bd->client.illume.win_state.state =
9493            ecore_x_e_illume_window_state_get(bd->client.win);
9494         bd->client.illume.win_state.fetch.state = 0;
9495      }
9496    if (bd->changes.shape)
9497      {
9498         Ecore_X_Rectangle *rects;
9499         int num;
9500
9501         bd->changes.shape = 0;
9502         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
9503         if (rects)
9504           {
9505              int cw = 0, ch = 0;
9506
9507              /* This doesn't fix the race, but makes it smaller. we detect
9508               * this and if cw and ch != client w/h then mark this as needing
9509               * a shape change again to fixup next event loop.
9510               */
9511              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9512              if ((cw != bd->client.w) || (ch != bd->client.h))
9513                bd->changes.shape = 1;
9514              if ((num == 1) &&
9515                  (rects[0].x == 0) &&
9516                  (rects[0].y == 0) &&
9517                  ((int)rects[0].width == cw) &&
9518                  ((int)rects[0].height == ch))
9519                {
9520                   if (bd->client.shaped)
9521                     {
9522                        bd->client.shaped = 0;
9523                        if (!bd->bordername)
9524                          bd->client.border.changed = 1;
9525                     }
9526                }
9527              else
9528                {
9529                   if (!bd->client.shaped)
9530                     {
9531                        bd->client.shaped = 1;
9532                        if (!bd->bordername)
9533                          bd->client.border.changed = 1;
9534                     }
9535                }
9536              free(rects);
9537           }
9538         else
9539           {
9540              // FIXME: no rects i think can mean... totally empty window
9541              bd->client.shaped = 0;
9542              if (!bd->bordername)
9543                bd->client.border.changed = 1;
9544           }
9545         bd->need_shape_merge = 1;
9546      }
9547    if (bd->changes.shape_input)
9548      {
9549         Ecore_X_Rectangle *rects;
9550         int num;
9551
9552         bd->changes.shape_input = 0;
9553         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
9554         if (rects)
9555           {
9556              int cw = 0, ch = 0;
9557
9558              /* This doesn't fix the race, but makes it smaller. we detect
9559               * this and if cw and ch != client w/h then mark this as needing
9560               * a shape change again to fixup next event loop.
9561               */
9562              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9563              if ((cw != bd->client.w) || (ch != bd->client.h))
9564                bd->changes.shape_input = 1;
9565              if ((num == 1) &&
9566                  (rects[0].x == 0) &&
9567                  (rects[0].y == 0) &&
9568                  ((int)rects[0].width == cw) &&
9569                  ((int)rects[0].height == ch))
9570                {
9571                   if (bd->shaped_input)
9572                     {
9573                        bd->shaped_input = 0;
9574                        if (!bd->bordername)
9575                          bd->client.border.changed = 1;
9576                     }
9577                }
9578              else
9579                {
9580                   if (!bd->shaped_input)
9581                     {
9582                        bd->shaped_input = 1;
9583                        if (!bd->bordername)
9584                          bd->client.border.changed = 1;
9585                     }
9586                }
9587              free(rects);
9588           }
9589         else
9590           {
9591              bd->shaped_input = 1;
9592              if (!bd->bordername)
9593                bd->client.border.changed = 1;
9594           }
9595         bd->need_shape_merge = 1;
9596      }
9597    if (bd->client.mwm.fetch.hints)
9598      {
9599         int pb;
9600
9601         bd->client.mwm.exists =
9602           ecore_x_mwm_hints_get(bd->client.win,
9603                                 &bd->client.mwm.func,
9604                                 &bd->client.mwm.decor,
9605                                 &bd->client.mwm.input);
9606         pb = bd->client.mwm.borderless;
9607         bd->client.mwm.borderless = 0;
9608         if (bd->client.mwm.exists)
9609           {
9610              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
9611                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
9612                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
9613                bd->client.mwm.borderless = 1;
9614           }
9615         if (bd->client.mwm.borderless != pb)
9616           {
9617              if ((!bd->lock_border) || (!bd->client.border.name))
9618                bd->client.border.changed = 1;
9619           }
9620         bd->client.mwm.fetch.hints = 0;
9621         rem_change = 1;
9622      }
9623    if (bd->client.e.fetch.video_parent)
9624      {
9625         /* unlinking child/parent */
9626         if (bd->client.e.state.video_parent_border != NULL)
9627           {
9628              bd->client.e.state.video_parent_border->client.e.state.video_child =
9629                eina_list_remove
9630                (bd->client.e.state.video_parent_border->client.e.state.video_child,
9631                    bd);
9632           }
9633
9634         ecore_x_window_prop_card32_get(bd->client.win,
9635                                        ECORE_X_ATOM_E_VIDEO_PARENT,
9636                                        &bd->client.e.state.video_parent,
9637                                        1);
9638
9639         /* linking child/parent */
9640         if (bd->client.e.state.video_parent != 0)
9641           {
9642              E_Border *tmp;
9643              Eina_List *l;
9644
9645              EINA_LIST_FOREACH(borders, l, tmp)
9646                if (tmp->client.win == bd->client.e.state.video_parent)
9647                  {
9648                     /* fprintf(stderr, "child added to parent \\o/\n"); */
9649                     bd->client.e.state.video_parent_border = tmp;
9650                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
9651                                                                        bd);
9652                     if (bd->desk != tmp->desk)
9653                       e_border_desk_set(bd, tmp->desk);
9654                     break;
9655                  }
9656           }
9657
9658         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
9659
9660         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
9661         rem_change = 1;
9662      }
9663    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
9664      {
9665         unsigned int xy[2];
9666
9667         ecore_x_window_prop_card32_get(bd->client.win,
9668                                        ECORE_X_ATOM_E_VIDEO_POSITION,
9669                                        xy,
9670                                        2);
9671         bd->client.e.state.video_position.x = xy[0];
9672         bd->client.e.state.video_position.y = xy[1];
9673         bd->client.e.state.video_position.updated = 1;
9674         bd->client.e.fetch.video_position = 0;
9675         bd->x = bd->client.e.state.video_position.x;
9676         bd->y = bd->client.e.state.video_position.y;
9677
9678         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
9679      }
9680    if (bd->client.netwm.update.state)
9681      {
9682         e_hints_window_state_set(bd);
9683         /* Some stats might change the border, like modal */
9684         if (((!bd->lock_border) || (!bd->client.border.name)) &&
9685             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
9686           {
9687              bd->client.border.changed = 1;
9688           }
9689         if (bd->parent)
9690           {
9691              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9692                {
9693                   bd->parent->modal = bd;
9694                   if (bd->parent->focused)
9695                     e_border_focus_set(bd, 1, 1);
9696                }
9697           }
9698         else if (bd->leader)
9699           {
9700              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9701                {
9702                   bd->leader->modal = bd;
9703                   if (bd->leader->focused)
9704                     e_border_focus_set(bd, 1, 1);
9705                   else
9706                     {
9707                        Eina_List *l;
9708                        E_Border *child;
9709
9710                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9711                          {
9712                             if ((child != bd) && (child->focused))
9713                               e_border_focus_set(bd, 1, 1);
9714                          }
9715                     }
9716                }
9717           }
9718         bd->client.netwm.update.state = 0;
9719      }
9720
9721    if (bd->new_client)
9722      {
9723         E_Event_Border_Add *ev;
9724         E_Exec_Instance *inst;
9725
9726         ev = E_NEW(E_Event_Border_Add, 1);
9727         ev->border = bd;
9728         e_object_ref(E_OBJECT(bd));
9729         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
9730         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
9731
9732         if ((!bd->lock_border) || (!bd->client.border.name))
9733           bd->client.border.changed = 1;
9734
9735           {
9736              char *str = NULL;
9737
9738              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
9739                  ((bd->client.icccm.client_leader > 0) &&
9740                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
9741                 )
9742                {
9743                   if (!strncmp(str, "E_START|", 8))
9744                     {
9745                        int id;
9746
9747                        id = atoi(str + 8);
9748                        if (id > 0) bd->client.netwm.startup_id = id;
9749                     }
9750                   free(str);
9751                }
9752           }
9753         /* It's ok not to have fetch flag, should only be set on startup
9754          *     * and not changed. */
9755         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
9756           {
9757              if (bd->client.icccm.client_leader)
9758                {
9759                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
9760                     bd->client.netwm.pid = -1;
9761                }
9762              else
9763                bd->client.netwm.pid = -1;
9764           }
9765
9766         if (!bd->re_manage)
9767           {
9768              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
9769                                                         bd->client.netwm.pid);
9770              if ((inst) && (inst->used == 0))
9771                {
9772                   E_Zone *zone;
9773                   E_Desk *desk;
9774
9775                   inst->used++;
9776                   zone = e_container_zone_number_get(bd->zone->container,
9777                                                      inst->screen);
9778                   if (zone) e_border_zone_set(bd, zone);
9779                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
9780                                           inst->desk_y);
9781                   if (desk) e_border_desk_set(bd, desk);
9782                   e_exec_instance_found(inst);
9783                }
9784
9785              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
9786                {
9787                   E_Border *bdl = NULL;
9788
9789                   bdl = bd->parent;
9790                   if (!bdl)
9791                     {
9792                        if (bd->leader) bdl = bd->leader;
9793                     }
9794                   if (!bdl)
9795                     {
9796                        E_Border *child;
9797                        E_Border_List *bl;
9798
9799                        bl = e_container_border_list_first(bd->zone->container);
9800                        while ((child = e_container_border_list_next(bl)))
9801                          {
9802                             if (child == bd) continue;
9803                             if (e_object_is_del(E_OBJECT(child))) continue;
9804                             if ((bd->client.icccm.client_leader) &&
9805                                 (child->client.icccm.client_leader ==
9806                                     bd->client.icccm.client_leader))
9807                               {
9808                                  bdl = child;
9809                                  break;
9810                               }
9811                          }
9812                        e_container_border_list_free(bl);
9813                     }
9814                   if (bdl)
9815                     {
9816                        if (bdl->zone)
9817                          e_border_zone_set(bd, bdl->zone);
9818                        if (bdl->desk)
9819                          e_border_desk_set(bd, bdl->desk);
9820                        else
9821                          e_border_stick(bd);
9822                     }
9823                }
9824           }
9825      }
9826
9827 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9828    if (need_desk_set)
9829      {
9830         E_Container *con = bd->zone->container;
9831         E_Desk *desk = NULL;
9832         Eina_List *l;
9833         const char *str;
9834         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
9835           {
9836              desk = e_container_desk_window_profile_get(con, str);
9837              if (desk)
9838                {
9839                   if (bd->desk != desk)
9840                     {
9841                        bd->client.e.state.profile = eina_stringshare_add(str);
9842                        if (bd->zone != desk->zone)
9843                          e_border_zone_set(bd, desk->zone);
9844                        e_border_desk_set(bd, desk);
9845                     }
9846                   break;
9847                }
9848           }
9849      }
9850 #endif
9851 #ifdef _F_ZONE_WINDOW_ROTATION_
9852    if ((e_config->wm_win_rotation) &&
9853        (need_rotation_set))
9854      {
9855         ELB(ELBT_ROT, "NEED ROT", bd->client.win);
9856         _e_border_rotation_check(bd);
9857      }
9858 #endif
9859
9860    /* PRE_POST_FETCH calls e_remember apply for new client */
9861    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
9862    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
9863    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
9864
9865    if (bd->need_reparent)
9866      {
9867         if (!bd->internal)
9868           ecore_x_window_save_set_add(bd->client.win);
9869         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
9870         if (bd->visible)
9871           {
9872              if ((bd->new_client) && (bd->internal) &&
9873                  (bd->internal_ecore_evas))
9874                ecore_evas_show(bd->internal_ecore_evas);
9875              ecore_x_window_show(bd->client.win);
9876           }
9877         bd->need_reparent = 0;
9878      }
9879
9880    if ((bd->client.border.changed) && (!bd->shaded) &&
9881        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
9882      {
9883         const char *bordername;
9884
9885         if (bd->fullscreen)
9886           bordername = "borderless";
9887         else if (bd->bordername)
9888           bordername = bd->bordername;
9889         else if ((bd->client.mwm.borderless) || (bd->borderless))
9890           bordername = "borderless";
9891         else if (((bd->client.icccm.transient_for != 0) ||
9892                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
9893                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
9894                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
9895           bordername = "noresize_dialog";
9896         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
9897                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
9898           bordername = "noresize";
9899         else if (bd->client.shaped)
9900           bordername = "shaped";
9901         else if ((!bd->client.icccm.accepts_focus) &&
9902                  (!bd->client.icccm.take_focus))
9903           bordername = "nofocus";
9904         else if (bd->client.icccm.urgent)
9905           bordername = "urgent";
9906         else if ((bd->client.icccm.transient_for != 0) ||
9907                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
9908           bordername = "dialog";
9909         else if (bd->client.netwm.state.modal)
9910           bordername = "modal";
9911         else if ((bd->client.netwm.state.skip_taskbar) ||
9912                  (bd->client.netwm.state.skip_pager))
9913           bordername = "skipped";
9914         else if ((bd->internal) && (bd->client.icccm.class) &&
9915                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
9916           bordername = "internal_fileman";
9917         else
9918           bordername = e_config->theme_default_border_style;
9919         if (!bordername) bordername = "default";
9920
9921         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
9922           {
9923              Evas_Object *o;
9924              char buf[4096];
9925              int ok;
9926
9927              bd->changes.border = 1;
9928              eina_stringshare_replace(&bd->client.border.name, bordername);
9929
9930              if (bd->bg_object)
9931                {
9932                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
9933                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
9934                   bd->changes.size = 1;
9935                   evas_object_del(bd->bg_object);
9936                }
9937              o = edje_object_add(bd->bg_evas);
9938              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
9939              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
9940              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
9941                {
9942                   if (bd->client.border.name != e_config->theme_default_border_style)
9943                     {
9944                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
9945                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
9946                     }
9947                   if (!ok)
9948                     {
9949                        ok = e_theme_edje_object_set(o, "base/theme/borders",
9950                                                     "e/widgets/border/default/border");
9951                        if (ok)
9952                          {
9953                             /* Reset default border style to default */
9954                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
9955                             e_config_save_queue();
9956                          }
9957                     }
9958                }
9959
9960              bd->shaped = 0;
9961              if (ok)
9962                {
9963                   const char *shape_option, *argb_option;
9964                   int use_argb = 0;
9965
9966                   bd->bg_object = o;
9967
9968                   if ((e_config->use_composite) && (!bd->client.argb))
9969                     {
9970                        argb_option = edje_object_data_get(o, "argb");
9971                        if ((argb_option) && (!strcmp(argb_option, "1")))
9972                          use_argb = 1;
9973
9974                        if (use_argb != bd->argb)
9975                          _e_border_frame_replace(bd, use_argb);
9976
9977                        o = bd->bg_object;
9978                     }
9979
9980                   if (!bd->argb)
9981                     {
9982                        shape_option = edje_object_data_get(o, "shaped");
9983                        if ((shape_option) && (!strcmp(shape_option, "1")))
9984                          bd->shaped = 1;
9985                     }
9986
9987                   if (bd->client.netwm.name)
9988                     edje_object_part_text_set(o, "e.text.title",
9989                                               bd->client.netwm.name);
9990                   else if (bd->client.icccm.title)
9991                     edje_object_part_text_set(o, "e.text.title",
9992                                               bd->client.icccm.title);
9993                }
9994              else
9995                {
9996                   evas_object_del(o);
9997                   bd->bg_object = NULL;
9998                }
9999
10000              _e_border_client_inset_calc(bd);
10001
10002              bd->w += (bd->client_inset.l + bd->client_inset.r);
10003              bd->h += (bd->client_inset.t + bd->client_inset.b);
10004              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
10005              bd->changes.size = 1;
10006              /*  really needed ? */
10007              ecore_x_window_move(bd->client.shell_win,
10008                                  bd->client_inset.l,
10009                                  bd->client_inset.t);
10010
10011              if (bd->maximized != E_MAXIMIZE_NONE)
10012                {
10013                   E_Maximize maximized = bd->maximized;
10014
10015                   /* to force possible resizes */
10016                   bd->maximized = E_MAXIMIZE_NONE;
10017
10018                   _e_border_maximize(bd, maximized);
10019
10020                   /* restore maximized state */
10021                   bd->maximized = maximized;
10022
10023                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
10024                                                bd->maximized & E_MAXIMIZE_VERTICAL);
10025                }
10026              if (bd->bg_object)
10027                {
10028                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
10029                                                   _e_border_cb_signal_bind, bd);
10030                   if (bd->focused)
10031                     {
10032                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
10033                        if (bd->icon_object)
10034                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10035                     }
10036                   if (bd->shaded)
10037                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
10038                   if (bd->sticky)
10039                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
10040                   if (bd->hung)
10041                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
10042                   // FIXME: in eval -do differently
10043                   //         edje_object_message_signal_process(bd->bg_object);
10044                   //         e_border_frame_recalc(bd);
10045
10046                   evas_object_move(bd->bg_object, 0, 0);
10047                   evas_object_resize(bd->bg_object, bd->w, bd->h);
10048                   evas_object_show(bd->bg_object);
10049                }
10050           }
10051         bd->client.border.changed = 0;
10052
10053         if (bd->icon_object)
10054           {
10055              if (bd->bg_object)
10056                {
10057                   evas_object_show(bd->icon_object);
10058                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10059                }
10060              else
10061                evas_object_hide(bd->icon_object);
10062           }
10063      }
10064
10065    if (rem_change) e_remember_update(bd);
10066
10067    if (change_urgent)
10068      {
10069         E_Event_Border_Urgent_Change *ev;
10070
10071         if (bd->client.icccm.urgent)
10072           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
10073         else
10074           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
10075
10076         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
10077         ev->border = bd;
10078         e_object_ref(E_OBJECT(bd));
10079         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
10080                         _e_border_event_border_urgent_change_free, NULL);
10081      }
10082
10083    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10084 }
10085
10086 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10087 static void
10088 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10089 {
10090    E_Border* temp_bd = NULL;
10091    E_Border* top_focusable_bd = NULL;
10092    Eina_Bool is_fully_obscured = EINA_FALSE;
10093    Ecore_X_XRegion *visible_region = NULL;
10094    Ecore_X_XRegion *win_region = NULL;
10095    Ecore_X_Rectangle visible_rect, win_rect;
10096    E_Border_List *bl;
10097
10098    // set the entire visible region as a root geometry
10099    visible_rect.x = bd->zone->x;
10100    visible_rect.y = bd->zone->y;
10101    visible_rect.width = bd->zone->w;
10102    visible_rect.height = bd->zone->h;
10103
10104    visible_region = ecore_x_xregion_new();
10105    if (!visible_region) return;
10106
10107    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10108
10109    bl = e_container_border_list_last(bd->zone->container);
10110    while ((temp_bd = e_container_border_list_prev(bl)))
10111      {
10112         if (temp_bd == bd) break;
10113
10114         if (temp_bd == focused) continue;
10115         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10116         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10117         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10118             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10119             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10120             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10121             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10122             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10123             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10124           {
10125              if (!top_focusable_bd)
10126                {
10127                   top_focusable_bd = temp_bd;
10128                }
10129
10130              win_rect.x = temp_bd->x;
10131              win_rect.y = temp_bd->y;
10132              win_rect.width = temp_bd->w;
10133              win_rect.height = temp_bd->h;
10134
10135              // if it stick out or is bigger than the entire visible region,
10136              // clip it by the entire visible's geometry.
10137              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10138                                   win_rect.width, win_rect.height,
10139                                   visible_rect.x, visible_rect.y,
10140                                   (int)(visible_rect.width), (int)(visible_rect.height));
10141
10142              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10143                {
10144                   win_region = ecore_x_xregion_new();
10145                   if (win_region)
10146                     {
10147                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10148                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10149                        ecore_x_xregion_free(win_region);
10150                        win_region = NULL;
10151
10152                        if (ecore_x_xregion_is_empty(visible_region))
10153                          {
10154                             is_fully_obscured = EINA_TRUE;
10155                             break;
10156                          }
10157                     }
10158                }
10159           }
10160      }
10161
10162    if (is_fully_obscured == EINA_TRUE)
10163      {
10164         e_border_focus_set(top_focusable_bd, 1, 1);
10165      }
10166    else
10167      {
10168         e_border_focus_set(bd, 1, 1);
10169      }
10170
10171    if (visible_region) ecore_x_xregion_free(visible_region);
10172    e_container_border_list_free(bl);
10173 }
10174
10175 static void
10176 _e_border_latest_stacked_focus(E_Border *bd)
10177 {
10178    E_Border *temp_bd;
10179    int root_w, root_h;
10180
10181    root_w = bd->zone->w;
10182    root_h = bd->zone->h;
10183
10184    Eina_List *l;
10185    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10186      {
10187         if (bd == temp_bd) continue;
10188         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10189         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10190
10191         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10192             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10193             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10194             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10195             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10196             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10197             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10198           {
10199              _e_border_latest_stacked_focus_check_set(temp_bd);
10200              break;
10201           }
10202      }
10203 }
10204
10205 static void
10206 _e_border_check_stack (E_Border *bd)
10207 {
10208    E_Border* temp_bd = NULL;
10209    E_Border* top_bd = NULL;
10210    int passed_focus = 0;
10211    int passed = 0;
10212    int root_w = bd->zone->w;
10213    int root_h = bd->zone->h;
10214
10215    E_Border_List *bl;
10216    bl = e_container_border_list_last(bd->zone->container);
10217    while ((temp_bd = e_container_border_list_prev(bl)))
10218      {
10219         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10220         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10221         if ((temp_bd != bd) &&
10222             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10223
10224         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10225            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10226            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10227            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10228            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10229            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10230            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10231           {
10232              if (bd == temp_bd)
10233                {
10234                   if (!passed)
10235                     {
10236                        e_border_focus_set_with_pointer(bd);
10237                        break;
10238                     }
10239                   else
10240                     {
10241                        if (!passed_focus)
10242                          {
10243                             e_border_focus_set_with_pointer(top_bd);
10244                          }
10245                        break;
10246                     }
10247                }
10248              else
10249                {
10250                   if (!passed)
10251                     {
10252                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10253                          {
10254                             if (!bd->lock_focus_out)
10255                               {
10256                                  e_border_focus_latest_set(bd);
10257                               }
10258                          }
10259                     }
10260                }
10261
10262              if (!passed)
10263                {
10264                   passed = 1;
10265                   top_bd = temp_bd;
10266                }
10267
10268              if (temp_bd == focused)
10269                {
10270                   passed_focus = 1;
10271                }
10272           }
10273      }
10274    e_container_border_list_free(bl);
10275 }
10276
10277 static void
10278 _e_border_focus_top_stack_set(E_Border* bd)
10279 {
10280    E_Border *temp_bd;
10281    int root_w, root_h;
10282
10283    root_w = bd->zone->w;
10284    root_h = bd->zone->h;
10285
10286    E_Border_List *bl;
10287    bl = e_container_border_list_last(bd->zone->container);
10288    while ((temp_bd = e_container_border_list_prev(bl)))
10289      {
10290         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10291         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10292         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
10293
10294         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10295            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10296            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10297            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10298            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10299            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10300            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10301           {
10302              if (!temp_bd->focused)
10303                {
10304                   /* this border is the top of the latest stack */
10305                   e_border_focus_set (temp_bd, 1, 1);
10306                }
10307              break;
10308           }
10309      }
10310    e_container_border_list_free(bl);
10311 }
10312 #endif
10313
10314 static void
10315 _e_border_eval(E_Border *bd)
10316 {
10317    E_Event_Border_Property *event;
10318    E_Border_Pending_Move_Resize *pnd;
10319    int rem_change = 0;
10320    int send_event = 1;
10321
10322    if (e_object_is_del(E_OBJECT(bd)))
10323      {
10324         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
10325         bd->changed = 0;
10326         return;
10327      }
10328
10329    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
10330
10331    if (bd->new_client)
10332      {
10333         int zx = 0, zy = 0, zw = 0, zh = 0;
10334
10335         if (bd->zone)
10336           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
10337
10338         /*
10339          * Limit maximum size of windows to useful geometry
10340          */
10341         // TODO: temoporary limited maximize algorithm
10342         // ->
10343         /*if (bd->w > zw)
10344           rw = zw;
10345           else
10346           rw = bd->w;
10347
10348           if (bd->h > zh)
10349           rh = zh;
10350           else
10351           rh = bd->h;
10352
10353           if ((rw != bd->w) || (rh != bd->h))
10354           {
10355           bd->w = rw;
10356           bd->h = rh;
10357           e_border_resize (bd, bd->w, bd->h);
10358           }*/
10359         // <-
10360
10361         if (bd->re_manage)
10362           {
10363              bd->x -= bd->client_inset.l;
10364              bd->y -= bd->client_inset.t;
10365              bd->changes.pos = 1;
10366              bd->placed = 1;
10367           }
10368         else if ((!bd->placed) && (bd->client.icccm.request_pos))
10369           {
10370
10371              Ecore_X_Window_Attributes *att;
10372              int bw;
10373
10374              att = &bd->client.initial_attributes;
10375              bw = att->border * 2;
10376              switch (bd->client.icccm.gravity)
10377                {
10378                 case ECORE_X_GRAVITY_N:
10379                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10380                    bd->y = att->y;
10381                    break;
10382
10383                 case ECORE_X_GRAVITY_NE:
10384                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10385                    bd->y = att->y;
10386                    break;
10387
10388                 case ECORE_X_GRAVITY_E:
10389                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10390                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10391                    break;
10392
10393                 case ECORE_X_GRAVITY_SE:
10394                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10395                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10396                    break;
10397
10398                 case ECORE_X_GRAVITY_S:
10399                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10400                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10401                    break;
10402
10403                 case ECORE_X_GRAVITY_SW:
10404                    bd->x = att->x;
10405                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10406                    break;
10407
10408                 case ECORE_X_GRAVITY_W:
10409                    bd->x = att->x;
10410                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10411                    break;
10412
10413                 case ECORE_X_GRAVITY_CENTER:
10414                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10415                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10416                    break;
10417
10418                 case ECORE_X_GRAVITY_NW:
10419                 default:
10420                    bd->x = att->x;
10421                    bd->y = att->y;
10422                }
10423
10424              /*
10425               * This ensures that windows that like to open with a x/y
10426               * position smaller than returned by e_zone_useful_geometry_get()
10427               * are moved to useful positions.
10428               */
10429              // ->
10430              if (e_config->geometry_auto_move)
10431                {
10432                   if (bd->x < zx)
10433                     bd->x = zx;
10434
10435                   if (bd->y < zy)
10436                     bd->y = zy;
10437
10438                   if (bd->x + bd->w > zx + zw)
10439                     bd->x = zx + zw - bd->w;
10440
10441                   if (bd->y + bd->h > zy + zh)
10442                     bd->y = zy + zh - bd->h;
10443                   // <--
10444
10445                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
10446                     {
10447                        bd->changes.pos = 1;
10448                        bd->placed = 1;
10449                     }
10450                }
10451              else
10452                {
10453                   bd->changes.pos = 1;
10454                   bd->placed = 1;
10455                }
10456           }
10457         if (!bd->placed)
10458           {
10459              /* FIXME: special placement for dialogs etc. etc. etc goes
10460               * here */
10461              /* FIXME: what if parent is not on this desktop - or zone? */
10462              if ((bd->parent) && (bd->parent->visible))
10463                {
10464                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
10465                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
10466                   bd->changes.pos = 1;
10467                   bd->placed = 1;
10468                }
10469 #if 0
10470              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10471                {
10472                   /* TODO: Place in center of group */
10473                }
10474 #endif
10475              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
10476                {
10477                   bd->x = zx + ((zw - bd->w) / 2);
10478                   bd->y = zy + ((zh - bd->h) / 2);
10479                   bd->changes.pos = 1;
10480                   bd->placed = 1;
10481                }
10482           }
10483         if (!bd->placed)
10484           {
10485              Eina_List *skiplist = NULL;
10486              int new_x, new_y;
10487
10488              if (zw > bd->w)
10489                new_x = zx + (rand() % (zw - bd->w));
10490              else
10491                new_x = zx;
10492              if (zh > bd->h)
10493                new_y = zy + (rand() % (zh - bd->h));
10494              else
10495                new_y = zy;
10496
10497              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
10498                {
10499                   skiplist = eina_list_append(skiplist, bd);
10500                   if (bd->desk)
10501                     e_place_desk_region_smart(bd->desk, skiplist,
10502                                               bd->x, bd->y, bd->w, bd->h,
10503                                               &new_x, &new_y);
10504                   else
10505                     e_place_zone_region_smart(bd->zone, skiplist,
10506                                               bd->x, bd->y, bd->w, bd->h,
10507                                               &new_x, &new_y);
10508                   eina_list_free(skiplist);
10509                }
10510              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
10511                {
10512                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
10513                                       &new_x, &new_y);
10514                }
10515              else
10516                {
10517                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
10518                                       bd->client_inset.t, &new_x, &new_y);
10519                }
10520              bd->x = new_x;
10521              bd->y = new_y;
10522              bd->changes.pos = 1;
10523           }
10524
10525         EINA_LIST_FREE(bd->pending_move_resize, pnd)
10526           {
10527              if ((!bd->lock_client_location) && (pnd->move))
10528                {
10529                   bd->x = pnd->x;
10530                   bd->y = pnd->y;
10531                   bd->changes.pos = 1;
10532                   bd->placed = 1;
10533                   if (pnd->without_border)
10534                     {
10535                        bd->x -= bd->client_inset.l;
10536                        bd->y -= bd->client_inset.t;
10537                     }
10538                }
10539              if ((!bd->lock_client_size) && (pnd->resize))
10540                {
10541                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
10542                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
10543                   bd->client.w = pnd->w;
10544                   bd->client.h = pnd->h;
10545                   bd->changes.size = 1;
10546                }
10547
10548              free(pnd);
10549           }
10550
10551         /* Recreate state */
10552         e_hints_window_init(bd);
10553         if ((bd->client.e.state.centered) &&
10554             ((!bd->remember) ||
10555              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
10556           {
10557              bd->x = zx + (zw - bd->w) / 2;
10558              bd->y = zy + (zh - bd->h) / 2;
10559              bd->changes.pos = 1;
10560              bd->placed = 1;
10561           }
10562
10563         _e_border_client_move_resize_send(bd);
10564
10565         /* if the explicit geometry request asks for the app to be
10566          * in another zone - well move it there */
10567         {
10568            E_Zone *zone;
10569
10570            zone = e_container_zone_at_point_get(bd->zone->container,
10571                                                 bd->x + (bd->w / 2),
10572                                                 bd->y + (bd->h / 2));
10573            if (!zone)
10574              zone = e_container_zone_at_point_get(bd->zone->container,
10575                                                   bd->x,
10576                                                   bd->y);
10577            if (!zone)
10578              zone = e_container_zone_at_point_get(bd->zone->container,
10579                                                   bd->x + bd->w - 1,
10580                                                   bd->y);
10581            if (!zone)
10582              zone = e_container_zone_at_point_get(bd->zone->container,
10583                                                   bd->x + bd->w - 1,
10584                                                   bd->y + bd->h - 1);
10585            if (!zone)
10586              zone = e_container_zone_at_point_get(bd->zone->container,
10587                                                   bd->x,
10588                                                   bd->y + bd->h - 1);
10589            if ((zone) && (zone != bd->zone))
10590              e_border_zone_set(bd, zone);
10591         }
10592      }
10593
10594    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
10595
10596    /* effect changes to the window border itself */
10597    if ((bd->changes.shading))
10598      {
10599         /*  show at start of unshade (but don't hide until end of shade) */
10600         if (bd->shaded)
10601           ecore_x_window_raise(bd->client.shell_win);
10602         bd->changes.shading = 0;
10603         rem_change = 1;
10604      }
10605    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
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.shaded = 0;
10612         rem_change = 1;
10613      }
10614    else if ((bd->changes.shaded) && (bd->changes.pos))
10615      {
10616         if (bd->shaded)
10617           ecore_x_window_lower(bd->client.shell_win);
10618         else
10619           ecore_x_window_raise(bd->client.shell_win);
10620         bd->changes.size = 1;
10621         bd->changes.shaded = 0;
10622         rem_change = 1;
10623      }
10624    else if ((bd->changes.shaded) && (bd->changes.size))
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.shaded = 0;
10631         rem_change = 1;
10632      }
10633    else if (bd->changes.shaded)
10634      {
10635         if (bd->shaded)
10636           ecore_x_window_lower(bd->client.shell_win);
10637         else
10638           ecore_x_window_raise(bd->client.shell_win);
10639         bd->changes.size = 1;
10640         bd->changes.shaded = 0;
10641         rem_change = 1;
10642      }
10643
10644    if (bd->changes.size)
10645      {
10646         int x = 0, y = 0, xx = 0, yy = 0;
10647
10648         if ((bd->shaded) && (!bd->shading))
10649           {
10650              evas_obscured_clear(bd->bg_evas);
10651           }
10652         else
10653           {
10654              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
10655              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
10656
10657              evas_obscured_clear(bd->bg_evas);
10658              evas_obscured_rectangle_add(bd->bg_evas,
10659                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
10660
10661              if (bd->shading)
10662                {
10663                   if (bd->shade.dir == E_DIRECTION_UP)
10664                     {
10665                        y = yy - bd->client.h;
10666                     }
10667                   else if (bd->shade.dir == E_DIRECTION_LEFT)
10668                     {
10669                        x = xx - bd->client.w;
10670                     }
10671                }
10672           }
10673
10674         if (bd->client.e.state.video)
10675           {
10676              if (bd->client.e.state.video_position.updated)
10677                {
10678                   ecore_x_window_move(bd->win,
10679                                       bd->client.e.state.video_parent_border->x +
10680                                       bd->client.e.state.video_parent_border->client_inset.l +
10681                                       bd->client.e.state.video_parent_border->fx.x +
10682                                       bd->client.e.state.video_position.x,
10683                                       bd->client.e.state.video_parent_border->y +
10684                                       bd->client.e.state.video_parent_border->client_inset.t +
10685                                       bd->client.e.state.video_parent_border->fx.y +
10686                                       bd->client.e.state.video_position.y);
10687                   bd->client.e.state.video_position.updated = 0;
10688                }
10689           }
10690         else if (!bd->changes.pos)
10691           {
10692              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
10693              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
10694              bd->post_resize = 1;
10695           }
10696         else
10697           {
10698              E_Border *tmp;
10699              Eina_List *l;
10700
10701              ecore_x_window_move_resize(bd->win,
10702                                         bd->x + bd->fx.x,
10703                                         bd->y + bd->fx.y,
10704                                         bd->w, bd->h);
10705
10706              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
10707                ecore_x_window_move(tmp->win,
10708                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
10709                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
10710           }
10711
10712         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
10713
10714         if ((!bd->shaded) || (bd->shading))
10715           ecore_x_window_move_resize(bd->client.shell_win,
10716                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
10717
10718         if (bd->internal_ecore_evas)
10719           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
10720         else if (!bd->client.e.state.video)
10721           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
10722
10723         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
10724         evas_object_resize(bd->bg_object, bd->w, bd->h);
10725         e_container_shape_resize(bd->shape, bd->w, bd->h);
10726         if (bd->changes.pos)
10727           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
10728
10729         _e_border_client_move_resize_send(bd);
10730
10731         bd->changes.pos = 0;
10732         bd->changes.size = 0;
10733         rem_change = 1;
10734      }
10735    else if (bd->changes.pos)
10736      {
10737         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
10738         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
10739         bd->post_move = 1;
10740
10741         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
10742
10743         _e_border_client_move_resize_send(bd);
10744
10745         bd->changes.pos = 0;
10746         rem_change = 1;
10747      }
10748
10749    if (bd->changes.reset_gravity)
10750      {
10751         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
10752         bd->changes.reset_gravity = 0;
10753         rem_change = 1;
10754      }
10755
10756    if (bd->need_shape_merge)
10757      {
10758         _e_border_shape_input_rectangle_set(bd);
10759         if ((bd->shaped) || (bd->client.shaped))
10760           {
10761              Ecore_X_Window twin, twin2;
10762              int x, y;
10763
10764              twin = ecore_x_window_override_new
10765                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
10766              if (bd->shaped)
10767                ecore_x_window_shape_window_set(twin, bd->bg_win);
10768              else
10769                {
10770                   Ecore_X_Rectangle rects[4];
10771
10772                   rects[0].x = 0;
10773                   rects[0].y = 0;
10774                   rects[0].width = bd->w;
10775                   rects[0].height = bd->client_inset.t;
10776                   rects[1].x = 0;
10777                   rects[1].y = bd->client_inset.t;
10778                   rects[1].width = bd->client_inset.l;
10779                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
10780                   rects[2].x = bd->w - bd->client_inset.r;
10781                   rects[2].y = bd->client_inset.t;
10782                   rects[2].width = bd->client_inset.r;
10783                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
10784                   rects[3].x = 0;
10785                   rects[3].y = bd->h - bd->client_inset.b;
10786                   rects[3].width = bd->w;
10787                   rects[3].height = bd->client_inset.b;
10788                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
10789                }
10790              twin2 = ecore_x_window_override_new
10791                (bd->zone->container->scratch_win, 0, 0,
10792                 bd->w - bd->client_inset.l - bd->client_inset.r,
10793                 bd->h - bd->client_inset.t - bd->client_inset.b);
10794              x = 0;
10795              y = 0;
10796              if ((bd->shading) || (bd->shaded))
10797                {
10798                   if (bd->shade.dir == E_DIRECTION_UP)
10799                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
10800                   else if (bd->shade.dir == E_DIRECTION_LEFT)
10801                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
10802                }
10803              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
10804                                                 x, y);
10805              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
10806                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
10807                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
10808              ecore_x_window_shape_window_add_xy(twin, twin2,
10809                                                 bd->client_inset.l,
10810                                                 bd->client_inset.t);
10811              ecore_x_window_free(twin2);
10812              ecore_x_window_shape_window_set(bd->win, twin);
10813              ecore_x_window_free(twin);
10814           }
10815         else
10816           ecore_x_window_shape_mask_set(bd->win, 0);
10817         //      bd->need_shape_export = 1;
10818         bd->need_shape_merge = 0;
10819      }
10820
10821    if (bd->need_shape_export)
10822      {
10823         Ecore_X_Rectangle *rects, *orects;
10824         int num;
10825
10826         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
10827         if (rects)
10828           {
10829              int changed;
10830
10831              changed = 1;
10832              if ((num == bd->shape_rects_num) && (bd->shape_rects))
10833                {
10834                   int i;
10835
10836                   orects = bd->shape_rects;
10837                   changed = 0;
10838                   for (i = 0; i < num; i++)
10839                     {
10840                        if (rects[i].x < 0)
10841                          {
10842                             rects[i].width -= rects[i].x;
10843                             rects[i].x = 0;
10844                          }
10845                        if ((rects[i].x + (int)rects[i].width) > bd->w)
10846                          rects[i].width = rects[i].width - rects[i].x;
10847                        if (rects[i].y < 0)
10848                          {
10849                             rects[i].height -= rects[i].y;
10850                             rects[i].y = 0;
10851                          }
10852                        if ((rects[i].y + (int)rects[i].height) > bd->h)
10853                          rects[i].height = rects[i].height - rects[i].y;
10854
10855                        if ((orects[i].x != rects[i].x) ||
10856                            (orects[i].y != rects[i].y) ||
10857                            (orects[i].width != rects[i].width) ||
10858                            (orects[i].height != rects[i].height))
10859                          {
10860                             changed = 1;
10861                             break;
10862                          }
10863                     }
10864                }
10865              if (changed)
10866                {
10867                   if (bd->client.shaped)
10868                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
10869                   else
10870                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
10871                   E_FREE(bd->shape_rects);
10872                   bd->shape_rects = rects;
10873                   bd->shape_rects_num = num;
10874                   e_container_shape_rects_set(bd->shape, rects, num);
10875                }
10876              else
10877                free(rects);
10878           }
10879         else
10880           {
10881              E_FREE(bd->shape_rects);
10882              bd->shape_rects = NULL;
10883              bd->shape_rects_num = 0;
10884              e_container_shape_rects_set(bd->shape, NULL, 0);
10885           }
10886         bd->need_shape_export = 0;
10887      }
10888
10889    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
10890      {
10891         int x, y;
10892
10893         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
10894         if ((!bd->placed) && (!bd->re_manage) &&
10895             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
10896             (!((bd->client.icccm.transient_for != 0) ||
10897                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
10898             (!bdmove) && (!bdresize))
10899           {
10900              /* Set this window into moving state */
10901
10902              bd->cur_mouse_action = e_action_find("window_move");
10903              if (bd->cur_mouse_action)
10904                {
10905                   if ((!bd->cur_mouse_action->func.end_mouse) &&
10906                       (!bd->cur_mouse_action->func.end))
10907                     bd->cur_mouse_action = NULL;
10908                   if (bd->cur_mouse_action)
10909                     {
10910                        bd->x = x - (bd->w >> 1);
10911                        bd->y = y - (bd->client_inset.t >> 1);
10912                        bd->changed = 1;
10913                        bd->changes.pos = 1;
10914
10915                        _e_border_client_move_resize_send(bd);
10916                     }
10917                }
10918           }
10919
10920         _e_border_show(bd);
10921
10922         if (bd->cur_mouse_action)
10923           {
10924              bd->moveinfo.down.x = bd->x + bd->fx.x;
10925              bd->moveinfo.down.y = bd->y + bd->fx.y;
10926              bd->moveinfo.down.w = bd->w;
10927              bd->moveinfo.down.h = bd->h;
10928              bd->mouse.current.mx = x;
10929              bd->mouse.current.my = y;
10930              bd->moveinfo.down.button = 0;
10931              bd->moveinfo.down.mx = x;
10932              bd->moveinfo.down.my = y;
10933
10934              grabbed = 1;
10935              e_object_ref(E_OBJECT(bd->cur_mouse_action));
10936              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
10937              if (e_config->border_raise_on_mouse_action)
10938                e_border_raise(bd);
10939              e_border_focus_set(bd, 1, 1);
10940           }
10941         bd->changes.visible = 0;
10942         rem_change = 1;
10943      }
10944
10945    if (bd->changes.icon)
10946      {
10947         if (bd->desktop)
10948           {
10949              efreet_desktop_free(bd->desktop);
10950              bd->desktop = NULL;
10951           }
10952         if (bd->icon_object)
10953           {
10954              evas_object_del(bd->icon_object);
10955              bd->icon_object = NULL;
10956           }
10957         if (bd->remember && bd->remember->prop.desktop_file)
10958           {
10959              const char *desktop = bd->remember->prop.desktop_file;
10960
10961              bd->desktop = efreet_desktop_get(desktop);
10962              if (!bd->desktop)
10963                bd->desktop = efreet_util_desktop_name_find(desktop);
10964           }
10965         if (!bd->desktop)
10966           {
10967              if ((bd->client.icccm.name) && (bd->client.icccm.class))
10968                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
10969                                                                bd->client.icccm.class);
10970           }
10971         if (!bd->desktop)
10972           {
10973              /* libreoffice and maybe others match window class
10974                 with .desktop file name */
10975              if (bd->client.icccm.class)
10976                {
10977                   char buf[128];
10978                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
10979                   bd->desktop = efreet_util_desktop_file_id_find(buf);
10980                }
10981           }
10982         if (!bd->desktop)
10983           {
10984              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
10985                                                       bd->client.netwm.pid);
10986              if (bd->desktop) efreet_desktop_ref(bd->desktop);
10987           }
10988         if (!bd->desktop && bd->client.icccm.name)
10989           {
10990              /* this works for most cases as fallback. useful when app is
10991                 run from a shell  */
10992              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
10993           }
10994         if (!bd->desktop && bd->client.icccm.transient_for)
10995           {
10996              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
10997              if (bd2 && bd2->desktop)
10998                {
10999                   efreet_desktop_ref(bd2->desktop);
11000                   bd->desktop = bd2->desktop;
11001                }
11002           }
11003         if (bd->desktop)
11004           {
11005              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
11006                                             bd->desktop->orig_path);
11007           }
11008
11009         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
11010         if ((bd->focused) && (bd->icon_object))
11011           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
11012         if (bd->bg_object)
11013           {
11014              evas_object_show(bd->icon_object);
11015              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
11016           }
11017         else
11018           evas_object_hide(bd->icon_object);
11019
11020         {
11021            E_Event_Border_Icon_Change *ev;
11022
11023            ev = E_NEW(E_Event_Border_Icon_Change, 1);
11024            ev->border = bd;
11025            e_object_ref(E_OBJECT(bd));
11026            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
11027            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
11028                            _e_border_event_border_icon_change_free, NULL);
11029         }
11030         bd->changes.icon = 0;
11031      }
11032
11033    bd->new_client = 0;
11034    bd->changed = 0;
11035    bd->changes.stack = 0;
11036    bd->changes.prop = 0;
11037
11038    if ((bd->take_focus) || (bd->want_focus))
11039      {
11040         bd->take_focus = 0;
11041 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11042         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
11043             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
11044             (bd->want_focus))
11045 #else // original
11046         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
11047 #endif
11048           {
11049              bd->want_focus = 0;
11050 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11051              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
11052                 _e_border_check_stack(bd);
11053              else
11054 #endif
11055              e_border_focus_set_with_pointer(bd);
11056           }
11057         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11058           {
11059              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
11060                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
11061                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
11062                    e_border_focused_get())))
11063                {
11064                   e_border_focus_set_with_pointer(bd);
11065                }
11066           }
11067         else
11068           {
11069              /* focus window by default when it is the only one on desk */
11070              E_Border *bd2 = NULL;
11071              Eina_List *l;
11072              EINA_LIST_FOREACH(focus_stack, l, bd2)
11073                {
11074                   if (bd == bd2) continue;
11075                   if ((!bd2->iconic) && (bd2->visible) &&
11076                       ((bd->desk == bd2->desk) || bd2->sticky))
11077                     break;
11078                }
11079
11080              if (!bd2)
11081                {
11082                   e_border_focus_set_with_pointer(bd);
11083                }
11084           }
11085      }
11086
11087    if (bd->need_maximize)
11088      {
11089         E_Maximize max;
11090         max = bd->maximized;
11091         bd->maximized = E_MAXIMIZE_NONE;
11092         e_border_maximize(bd, max);
11093         bd->need_maximize = 0;
11094      }
11095
11096    if (bd->need_fullscreen)
11097      {
11098         e_border_fullscreen(bd, e_config->fullscreen_policy);
11099         bd->need_fullscreen = 0;
11100      }
11101
11102    if (rem_change)
11103      e_remember_update(bd);
11104
11105    if (send_event) // FIXME: send only if a property changed - above need to
11106      { // check on that. for now - always send.
11107         event = E_NEW(E_Event_Border_Property, 1);
11108         event->border = bd;
11109         e_object_ref(E_OBJECT(bd));
11110         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11111      }
11112    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11113 }
11114
11115 static void
11116 _e_border_moveinfo_gather(E_Border   *bd,
11117                           const char *source)
11118 {
11119    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11120    else if (e_util_glob_match(source, "mouse,*,2"))
11121      bd->moveinfo.down.button = 2;
11122    else if (e_util_glob_match(source, "mouse,*,3"))
11123      bd->moveinfo.down.button = 3;
11124    else bd->moveinfo.down.button = 0;
11125    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11126      {
11127         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11128         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11129      }
11130    else
11131      {
11132         bd->moveinfo.down.mx = bd->mouse.current.mx;
11133         bd->moveinfo.down.my = bd->mouse.current.my;
11134      }
11135 }
11136
11137 static void
11138 _e_border_resize_handle(E_Border *bd)
11139 {
11140    int x, y, w, h;
11141    int new_x, new_y, new_w, new_h;
11142    int tw, th;
11143    Eina_List *skiplist = NULL;
11144
11145    x = bd->x;
11146    y = bd->y;
11147    w = bd->w;
11148    h = bd->h;
11149
11150    if ((bd->resize_mode == RESIZE_TR) ||
11151        (bd->resize_mode == RESIZE_R) ||
11152        (bd->resize_mode == RESIZE_BR))
11153      {
11154         if ((bd->moveinfo.down.button >= 1) &&
11155             (bd->moveinfo.down.button <= 3))
11156           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11157             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11158         else
11159           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11160      }
11161    else if ((bd->resize_mode == RESIZE_TL) ||
11162             (bd->resize_mode == RESIZE_L) ||
11163             (bd->resize_mode == RESIZE_BL))
11164      {
11165         if ((bd->moveinfo.down.button >= 1) &&
11166             (bd->moveinfo.down.button <= 3))
11167           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11168             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11169         else
11170           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11171      }
11172
11173    if ((bd->resize_mode == RESIZE_TL) ||
11174        (bd->resize_mode == RESIZE_T) ||
11175        (bd->resize_mode == RESIZE_TR))
11176      {
11177         if ((bd->moveinfo.down.button >= 1) &&
11178             (bd->moveinfo.down.button <= 3))
11179           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11180             (bd->mouse.current.my - bd->moveinfo.down.my);
11181         else
11182           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11183      }
11184    else if ((bd->resize_mode == RESIZE_BL) ||
11185             (bd->resize_mode == RESIZE_B) ||
11186             (bd->resize_mode == RESIZE_BR))
11187      {
11188         if ((bd->moveinfo.down.button >= 1) &&
11189             (bd->moveinfo.down.button <= 3))
11190           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11191             (bd->mouse.current.my - bd->moveinfo.down.my);
11192         else
11193           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11194      }
11195
11196    tw = bd->w;
11197    th = bd->h;
11198
11199    if ((bd->resize_mode == RESIZE_TL) ||
11200        (bd->resize_mode == RESIZE_L) ||
11201        (bd->resize_mode == RESIZE_BL))
11202      x += (tw - w);
11203    if ((bd->resize_mode == RESIZE_TL) ||
11204        (bd->resize_mode == RESIZE_T) ||
11205        (bd->resize_mode == RESIZE_TR))
11206      y += (th - h);
11207
11208    skiplist = eina_list_append(skiplist, bd);
11209    e_resist_container_border_position(bd->zone->container, skiplist,
11210                                       bd->x, bd->y, bd->w, bd->h,
11211                                       x, y, w, h,
11212                                       &new_x, &new_y, &new_w, &new_h);
11213    eina_list_free(skiplist);
11214
11215    w = new_w;
11216    h = new_h;
11217    e_border_resize_limit(bd, &new_w, &new_h);
11218    if ((bd->resize_mode == RESIZE_TL) ||
11219        (bd->resize_mode == RESIZE_L) ||
11220        (bd->resize_mode == RESIZE_BL))
11221      new_x += (w - new_w);
11222    if ((bd->resize_mode == RESIZE_TL) ||
11223        (bd->resize_mode == RESIZE_T) ||
11224        (bd->resize_mode == RESIZE_TR))
11225      new_y += (h - new_h);
11226
11227    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11228 }
11229
11230 static Eina_Bool
11231 _e_border_shade_animator(void *data)
11232 {
11233    E_Border *bd = data;
11234    double dt, val;
11235    double dur = bd->client.h / e_config->border_shade_speed;
11236
11237    dt = ecore_loop_time_get() - bd->shade.start;
11238    val = dt / dur;
11239
11240    if (val < 0.0) val = 0.0;
11241    else if (val > 1.0) val = 1.0;
11242
11243    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11244      {
11245         bd->shade.val =
11246            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
11247         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11248      }
11249    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
11250      {
11251         bd->shade.val =
11252            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
11253         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11254      }
11255    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
11256      {
11257         bd->shade.val =
11258            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
11259         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11260      }
11261    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
11262      {
11263         bd->shade.val =
11264            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11265         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11266      }
11267    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
11268      {
11269         bd->shade.val =
11270            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
11271         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11272      }
11273    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
11274      {
11275         bd->shade.val =
11276            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
11277         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11278      }
11279    else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
11280      {
11281         bd->shade.val =
11282            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.0);
11283         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11284      }
11285    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE)
11286      {
11287         bd->shade.val =
11288            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
11289         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11290      }
11291    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
11292      {
11293         bd->shade.val =
11294            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
11295         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11296      }
11297    else
11298      {
11299         bd->shade.val =
11300            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11301         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11302      }
11303
11304    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
11305    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
11306    else if (bd->shade.val > .999)
11307      bd->shade.val = 1.0;
11308
11309    if (bd->shade.dir == E_DIRECTION_UP)
11310      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11311    else if (bd->shade.dir == E_DIRECTION_DOWN)
11312      {
11313         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11314         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
11315         bd->changes.pos = 1;
11316      }
11317    else if (bd->shade.dir == E_DIRECTION_LEFT)
11318      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11319    else if (bd->shade.dir == E_DIRECTION_RIGHT)
11320      {
11321         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11322         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
11323         bd->changes.pos = 1;
11324      }
11325
11326    if ((bd->shaped) || (bd->client.shaped))
11327      {
11328         bd->need_shape_merge = 1;
11329         bd->need_shape_export = 1;
11330      }
11331    if (bd->shaped_input)
11332      {
11333         bd->need_shape_merge = 1;
11334      }
11335    bd->changes.size = 1;
11336    bd->changed = 1;
11337
11338    /* we're done */
11339    if (val == 1)
11340      {
11341         E_Event_Border_Resize *ev;
11342
11343         bd->shading = 0;
11344         bd->shaded = !(bd->shaded);
11345         bd->changes.size = 1;
11346         bd->changes.shaded = 1;
11347         bd->changes.shading = 1;
11348         bd->changed = 1;
11349         bd->shade.anim = NULL;
11350
11351         if (bd->shaded)
11352           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
11353         else
11354           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
11355         edje_object_message_signal_process(bd->bg_object);
11356         e_border_frame_recalc(bd);
11357
11358         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
11359         ev = E_NEW(E_Event_Border_Resize, 1);
11360         ev->border = bd;
11361         e_object_ref(E_OBJECT(bd));
11362 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
11363         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
11364         return ECORE_CALLBACK_CANCEL;
11365      }
11366    return ECORE_CALLBACK_RENEW;
11367 }
11368
11369 static void
11370 _e_border_event_border_resize_free(void *data __UNUSED__,
11371                                    void      *ev)
11372 {
11373    E_Event_Border_Resize *e;
11374
11375    e = ev;
11376 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
11377    e_object_unref(E_OBJECT(e->border));
11378    E_FREE(e);
11379 }
11380
11381 static void
11382 _e_border_event_border_move_free(void *data __UNUSED__,
11383                                  void      *ev)
11384 {
11385    E_Event_Border_Move *e;
11386
11387    e = ev;
11388 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
11389    e_object_unref(E_OBJECT(e->border));
11390    E_FREE(e);
11391 }
11392
11393 static void
11394 _e_border_event_border_add_free(void *data __UNUSED__,
11395                                 void      *ev)
11396 {
11397    E_Event_Border_Add *e;
11398
11399    e = ev;
11400 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
11401    e_object_unref(E_OBJECT(e->border));
11402    E_FREE(e);
11403 }
11404
11405 static void
11406 _e_border_event_border_remove_free(void *data __UNUSED__,
11407                                    void      *ev)
11408 {
11409    E_Event_Border_Remove *e;
11410
11411    e = ev;
11412 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
11413    e_object_unref(E_OBJECT(e->border));
11414    E_FREE(e);
11415 }
11416
11417 static void
11418 _e_border_event_border_show_free(void *data __UNUSED__,
11419                                  void      *ev)
11420 {
11421    E_Event_Border_Show *e;
11422
11423    e = ev;
11424 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
11425    e_object_unref(E_OBJECT(e->border));
11426    E_FREE(e);
11427 }
11428
11429 static void
11430 _e_border_event_border_hide_free(void *data __UNUSED__,
11431                                  void      *ev)
11432 {
11433    E_Event_Border_Hide *e;
11434
11435    e = ev;
11436 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
11437    e_object_unref(E_OBJECT(e->border));
11438    E_FREE(e);
11439 }
11440
11441 static void
11442 _e_border_event_border_iconify_free(void *data __UNUSED__,
11443                                     void      *ev)
11444 {
11445    E_Event_Border_Iconify *e;
11446
11447    e = ev;
11448 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
11449    e_object_unref(E_OBJECT(e->border));
11450    E_FREE(e);
11451 }
11452
11453 static void
11454 _e_border_event_border_uniconify_free(void *data __UNUSED__,
11455                                       void      *ev)
11456 {
11457    E_Event_Border_Uniconify *e;
11458
11459    e = ev;
11460 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
11461    e_object_unref(E_OBJECT(e->border));
11462    E_FREE(e);
11463 }
11464
11465 static void
11466 _e_border_event_border_stick_free(void *data __UNUSED__,
11467                                   void      *ev)
11468 {
11469    E_Event_Border_Stick *e;
11470
11471    e = ev;
11472 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
11473    e_object_unref(E_OBJECT(e->border));
11474    E_FREE(e);
11475 }
11476
11477 static void
11478 _e_border_event_border_unstick_free(void *data __UNUSED__,
11479                                     void      *ev)
11480 {
11481    E_Event_Border_Unstick *e;
11482
11483    e = ev;
11484 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
11485    e_object_unref(E_OBJECT(e->border));
11486    E_FREE(e);
11487 }
11488
11489 static void
11490 _e_border_event_border_zone_set_free(void *data __UNUSED__,
11491                                      void      *ev)
11492 {
11493    E_Event_Border_Zone_Set *e;
11494
11495    e = ev;
11496 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
11497    e_object_unref(E_OBJECT(e->border));
11498    e_object_unref(E_OBJECT(e->zone));
11499    E_FREE(e);
11500 }
11501
11502 static void
11503 _e_border_event_border_desk_set_free(void *data __UNUSED__,
11504                                      void      *ev)
11505 {
11506    E_Event_Border_Desk_Set *e;
11507
11508    e = ev;
11509 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
11510    e_object_unref(E_OBJECT(e->border));
11511    e_object_unref(E_OBJECT(e->desk));
11512    E_FREE(e);
11513 }
11514
11515 static void
11516 _e_border_event_border_stack_free(void *data __UNUSED__,
11517                                   void      *ev)
11518 {
11519    E_Event_Border_Stack *e;
11520
11521    e = ev;
11522 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
11523    e_object_unref(E_OBJECT(e->border));
11524    if (e->stack)
11525      {
11526 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
11527           e_object_unref(E_OBJECT(e->stack));
11528      }
11529    E_FREE(e);
11530 }
11531
11532 static void
11533 _e_border_event_border_icon_change_free(void *data __UNUSED__,
11534                                         void      *ev)
11535 {
11536    E_Event_Border_Icon_Change *e;
11537
11538    e = ev;
11539 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
11540    e_object_unref(E_OBJECT(e->border));
11541    E_FREE(e);
11542 }
11543
11544 static void
11545 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
11546                                           void      *ev)
11547 {
11548    E_Event_Border_Urgent_Change *e;
11549
11550    e = ev;
11551    e_object_unref(E_OBJECT(e->border));
11552    E_FREE(e);
11553 }
11554
11555 static void
11556 _e_border_event_border_focus_in_free(void *data __UNUSED__,
11557                                      void      *ev)
11558 {
11559    E_Event_Border_Focus_In *e;
11560
11561    e = ev;
11562    e_object_unref(E_OBJECT(e->border));
11563    E_FREE(e);
11564 }
11565
11566 static void
11567 _e_border_event_border_focus_out_free(void *data __UNUSED__,
11568                                       void      *ev)
11569 {
11570    E_Event_Border_Focus_Out *e;
11571
11572    e = ev;
11573    e_object_unref(E_OBJECT(e->border));
11574    E_FREE(e);
11575 }
11576
11577 static void
11578 _e_border_event_border_property_free(void *data __UNUSED__,
11579                                      void      *ev)
11580 {
11581    E_Event_Border_Property *e;
11582
11583    e = ev;
11584    e_object_unref(E_OBJECT(e->border));
11585    E_FREE(e);
11586 }
11587
11588 static void
11589 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
11590                                        void      *ev)
11591 {
11592    E_Event_Border_Fullscreen *e;
11593
11594    e = ev;
11595 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
11596    e_object_unref(E_OBJECT(e->border));
11597    E_FREE(e);
11598 }
11599
11600 static void
11601 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
11602                                          void      *ev)
11603 {
11604    E_Event_Border_Unfullscreen *e;
11605
11606    e = ev;
11607 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
11608    e_object_unref(E_OBJECT(e->border));
11609    E_FREE(e);
11610 }
11611
11612 #ifdef _F_ZONE_WINDOW_ROTATION_
11613 static void
11614 _e_border_event_border_rotation_free(void *data __UNUSED__,
11615                                      void      *ev)
11616 {
11617    E_Event_Border_Rotation *e;
11618
11619    e = ev;
11620    e_object_unref(E_OBJECT(e->border));
11621    E_FREE(e);
11622 }
11623 #endif
11624
11625 static void
11626 _e_border_zone_update(E_Border *bd)
11627 {
11628    E_Container *con;
11629    Eina_List *l;
11630    E_Zone *zone;
11631
11632    /* still within old zone - leave it there */
11633    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
11634                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
11635 #if _F_BORDER_CLIP_TO_ZONE_
11636      {
11637         _e_border_shape_input_clip_to_zone(bd);
11638         return;
11639      }
11640 #else
11641      return;
11642 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
11643    /* find a new zone */
11644    con = bd->zone->container;
11645    EINA_LIST_FOREACH(con->zones, l, zone)
11646      {
11647         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
11648                          zone->x, zone->y, zone->w, zone->h))
11649           {
11650              e_border_zone_set(bd, zone);
11651 #if _F_BORDER_CLIP_TO_ZONE_
11652              _e_border_shape_input_clip_to_zone(bd);
11653 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
11654              return;
11655           }
11656      }
11657 }
11658
11659 static int
11660 _e_border_resize_begin(E_Border *bd)
11661 {
11662    if (!bd->lock_user_stacking)
11663      {
11664         if (e_config->border_raise_on_mouse_action)
11665           e_border_raise(bd);
11666      }
11667    if ((bd->shaded) || (bd->shading) ||
11668        (bd->fullscreen) || (bd->lock_user_size))
11669      return 0;
11670
11671    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
11672      {
11673         grabbed = 0;
11674         return 0;
11675      }
11676
11677    if (bd->client.netwm.sync.request)
11678      {
11679         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
11680         bd->client.netwm.sync.serial = 1;
11681         bd->client.netwm.sync.wait = 0;
11682         bd->client.netwm.sync.send_time = ecore_loop_time_get();
11683      }
11684
11685    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
11686
11687    bdresize = bd;
11688    return 1;
11689 }
11690
11691 static int
11692 _e_border_resize_end(E_Border *bd)
11693 {
11694    if (grabbed)
11695      {
11696         e_grabinput_release(bd->win, bd->win);
11697         grabbed = 0;
11698      }
11699    if (bd->client.netwm.sync.alarm)
11700      {
11701         E_Border_Pending_Move_Resize *pnd;
11702
11703         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
11704         bd->client.netwm.sync.alarm = 0;
11705         /* resize to last geometry if sync alarm for it was not yet handled */
11706         if (bd->pending_move_resize)
11707           {
11708              bd->changed = 1;
11709              bd->changes.pos = 1;
11710              bd->changes.size = 1;
11711              _e_border_client_move_resize_send(bd);
11712           }
11713
11714         EINA_LIST_FREE(bd->pending_move_resize, pnd)
11715           E_FREE(pnd);
11716      }
11717
11718    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
11719
11720    bdresize = NULL;
11721
11722    /* If this border was maximized, we need to unset Maximized state or
11723     * on restart, E still thinks it's maximized */
11724    if (bd->maximized != E_MAXIMIZE_NONE)
11725      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
11726                                   bd->maximized & E_MAXIMIZE_NONE);
11727    return 1;
11728 }
11729
11730 static void
11731 _e_border_resize_update(E_Border *bd)
11732 {
11733    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
11734 }
11735
11736 static int
11737 _e_border_move_begin(E_Border *bd)
11738 {
11739    if (!bd->lock_user_stacking)
11740      {
11741         if (e_config->border_raise_on_mouse_action)
11742           e_border_raise(bd);
11743      }
11744    if ((bd->fullscreen) || (bd->lock_user_location))
11745      return 0;
11746
11747    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
11748      {
11749         grabbed = 0;
11750         return 0;
11751      }
11752 #if 0
11753    if (bd->client.netwm.sync.request)
11754      {
11755         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
11756         bd->client.netwm.sync.serial = 0;
11757         bd->client.netwm.sync.wait = 0;
11758         bd->client.netwm.sync.time = ecore_loop_time_get();
11759      }
11760 #endif
11761    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
11762
11763    bdmove = bd;
11764    return 1;
11765 }
11766
11767 static int
11768 _e_border_move_end(E_Border *bd)
11769 {
11770    if (grabbed)
11771      {
11772         e_grabinput_release(bd->win, bd->win);
11773         grabbed = 0;
11774      }
11775 #if 0
11776    if (bd->client.netwm.sync.alarm)
11777      {
11778         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
11779         bd->client.netwm.sync.alarm = 0;
11780      }
11781 #endif
11782    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
11783
11784    bdmove = NULL;
11785    return 1;
11786 }
11787
11788 static void
11789 _e_border_move_update(E_Border *bd)
11790 {
11791    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
11792 }
11793
11794 static Eina_Bool
11795 _e_border_cb_ping_poller(void *data)
11796 {
11797    E_Border *bd;
11798
11799    bd = data;
11800    if (bd->ping_ok)
11801      {
11802         if (bd->hung)
11803           {
11804              bd->hung = 0;
11805              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
11806              if (bd->kill_timer)
11807                {
11808                   ecore_timer_del(bd->kill_timer);
11809                   bd->kill_timer = NULL;
11810                }
11811           }
11812      }
11813    else
11814      {
11815         /* if time between last ping and now is greater
11816          * than half the ping interval... */
11817         if ((ecore_loop_time_get() - bd->ping) >
11818             ((e_config->ping_clients_interval *
11819               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
11820           {
11821              if (!bd->hung)
11822                {
11823                   bd->hung = 1;
11824                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
11825                   /* FIXME: if below dialog is up - hide it now */
11826                }
11827              if (bd->delete_requested)
11828                {
11829                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
11830                   e_border_act_kill_begin(bd);
11831                }
11832           }
11833      }
11834    bd->ping_poller = NULL;
11835    e_border_ping(bd);
11836    return ECORE_CALLBACK_CANCEL;
11837 }
11838
11839 static Eina_Bool
11840 _e_border_cb_kill_timer(void *data)
11841 {
11842    E_Border *bd;
11843
11844    bd = data;
11845 // dont wait until it's hung -
11846 //   if (bd->hung)
11847 //     {
11848         if (bd->client.netwm.pid > 1)
11849           kill(bd->client.netwm.pid, SIGKILL);
11850 //     }
11851    bd->kill_timer = NULL;
11852    return ECORE_CALLBACK_CANCEL;
11853 }
11854
11855 static void
11856 _e_border_pointer_resize_begin(E_Border *bd)
11857 {
11858    switch (bd->resize_mode)
11859      {
11860       case RESIZE_TL:
11861         e_pointer_type_push(bd->pointer, bd, "resize_tl");
11862         break;
11863
11864       case RESIZE_T:
11865         e_pointer_type_push(bd->pointer, bd, "resize_t");
11866         break;
11867
11868       case RESIZE_TR:
11869         e_pointer_type_push(bd->pointer, bd, "resize_tr");
11870         break;
11871
11872       case RESIZE_R:
11873         e_pointer_type_push(bd->pointer, bd, "resize_r");
11874         break;
11875
11876       case RESIZE_BR:
11877         e_pointer_type_push(bd->pointer, bd, "resize_br");
11878         break;
11879
11880       case RESIZE_B:
11881         e_pointer_type_push(bd->pointer, bd, "resize_b");
11882         break;
11883
11884       case RESIZE_BL:
11885         e_pointer_type_push(bd->pointer, bd, "resize_bl");
11886         break;
11887
11888       case RESIZE_L:
11889         e_pointer_type_push(bd->pointer, bd, "resize_l");
11890         break;
11891      }
11892 }
11893
11894 static void
11895 _e_border_pointer_resize_end(E_Border *bd)
11896 {
11897    switch (bd->resize_mode)
11898      {
11899       case RESIZE_TL:
11900         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
11901         break;
11902
11903       case RESIZE_T:
11904         e_pointer_type_pop(bd->pointer, bd, "resize_t");
11905         break;
11906
11907       case RESIZE_TR:
11908         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
11909         break;
11910
11911       case RESIZE_R:
11912         e_pointer_type_pop(bd->pointer, bd, "resize_r");
11913         break;
11914
11915       case RESIZE_BR:
11916         e_pointer_type_pop(bd->pointer, bd, "resize_br");
11917         break;
11918
11919       case RESIZE_B:
11920         e_pointer_type_pop(bd->pointer, bd, "resize_b");
11921         break;
11922
11923       case RESIZE_BL:
11924         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
11925         break;
11926
11927       case RESIZE_L:
11928         e_pointer_type_pop(bd->pointer, bd, "resize_l");
11929         break;
11930      }
11931 }
11932
11933 static void
11934 _e_border_pointer_move_begin(E_Border *bd)
11935 {
11936    e_pointer_type_push(bd->pointer, bd, "move");
11937 }
11938
11939 static void
11940 _e_border_pointer_move_end(E_Border *bd)
11941 {
11942    e_pointer_type_pop(bd->pointer, bd, "move");
11943 }
11944
11945 static Eina_List *_e_border_hooks = NULL;
11946 static int _e_border_hooks_delete = 0;
11947 static int _e_border_hooks_walking = 0;
11948
11949 static void
11950 _e_border_hooks_clean(void)
11951 {
11952    Eina_List *l, *ln;
11953    E_Border_Hook *bh;
11954
11955    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
11956      {
11957         if (bh->delete_me)
11958           {
11959              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
11960              free(bh);
11961           }
11962      }
11963 }
11964
11965 static void
11966 _e_border_hook_call(E_Border_Hook_Point hookpoint,
11967                     void               *bd)
11968 {
11969    Eina_List *l;
11970    E_Border_Hook *bh;
11971
11972    _e_border_hooks_walking++;
11973    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
11974      {
11975         if (bh->delete_me) continue;
11976         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
11977      }
11978    _e_border_hooks_walking--;
11979    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
11980      _e_border_hooks_clean();
11981 }
11982
11983 EAPI E_Border_Hook *
11984 e_border_hook_add(E_Border_Hook_Point               hookpoint,
11985                   void                              (*func)(void *data,
11986                                               void *bd),
11987                   void                             *data)
11988 {
11989    E_Border_Hook *bh;
11990
11991    bh = E_NEW(E_Border_Hook, 1);
11992    if (!bh) return NULL;
11993    bh->hookpoint = hookpoint;
11994    bh->func = func;
11995    bh->data = data;
11996    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
11997    return bh;
11998 }
11999
12000 EAPI void
12001 e_border_hook_del(E_Border_Hook *bh)
12002 {
12003    bh->delete_me = 1;
12004    if (_e_border_hooks_walking == 0)
12005      {
12006         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
12007         free(bh);
12008      }
12009    else
12010      _e_border_hooks_delete++;
12011 }
12012
12013 EAPI void
12014 e_border_focus_track_freeze(void)
12015 {
12016    focus_track_frozen++;
12017 }
12018
12019 EAPI void
12020 e_border_focus_track_thaw(void)
12021 {
12022    focus_track_frozen--;
12023 }
12024
12025 EAPI E_Border *
12026 e_border_under_pointer_get(E_Desk   *desk,
12027                            E_Border *exclude)
12028 {
12029    E_Border *bd = NULL, *cbd;
12030    Eina_List *l;
12031    int x, y;
12032
12033    /* We need to ensure that we can get the container window for the
12034     * zone of either the given desk or the desk of the excluded
12035     * window, so return if neither is given */
12036    if (desk)
12037      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
12038    else if (exclude)
12039      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
12040    else
12041      return NULL;
12042
12043    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
12044      {
12045         if (!cbd) continue;
12046         /* If a border was specified which should be excluded from the list
12047          * (because it will be closed shortly for example), skip */
12048         if ((exclude) && (cbd == exclude)) continue;
12049         if ((desk) && (cbd->desk != desk)) continue;
12050         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
12051           continue;
12052         /* If the layer is higher, the position of the window is higher
12053          * (always on top vs always below) */
12054         if (!bd || (cbd->layer > bd->layer))
12055           {
12056              bd = cbd;
12057              break;
12058           }
12059      }
12060    return bd;
12061 }
12062
12063 static Eina_Bool
12064 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
12065 {
12066    if (warp_to)
12067      {
12068         int x, y;
12069         double spd;
12070
12071         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
12072         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
12073             (y - warp_y) > 5 || (y - warp_y) < -5)
12074           {
12075              /* User moved the mouse, so stop warping */
12076              warp_to = 0;
12077              goto cleanup;
12078           }
12079
12080         /* We just use the same warp speed as configured
12081          * for the windowlist */
12082         spd = e_config->winlist_warp_speed;
12083         x = warp_x;
12084         y = warp_y;
12085         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12086         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12087         if (warp_x == x && warp_y == y)
12088           {
12089              warp_x = warp_to_x;
12090              warp_y = warp_to_y;
12091              warp_to = 0;
12092              goto cleanup;
12093           }
12094         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12095         return ECORE_CALLBACK_RENEW;
12096      }
12097  cleanup:
12098    ecore_timer_del(warp_timer);
12099    warp_timer = NULL;
12100    return ECORE_CALLBACK_CANCEL;
12101 }
12102
12103 EAPI int
12104 e_border_pointer_warp_to_center(E_Border *bd)
12105 {
12106    int x, y;
12107
12108    /* Do not slide pointer when disabled (probably breaks focus
12109     * on sloppy/mouse focus but requested by users). */
12110    if (!e_config->pointer_slide) return 0;
12111    /* Only warp the pointer if it is not already in the area of
12112     * the given border */
12113    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12114    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12115        (y >= bd->y) && (y <= (bd->y + bd->h)))
12116      return 0;
12117
12118    warp_to_x = bd->x + (bd->w / 2);
12119    if (warp_to_x < (bd->zone->x + 1))
12120      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12121    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12122      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12123
12124    warp_to_y = bd->y + (bd->h / 2);
12125    if (warp_to_y < (bd->zone->y + 1))
12126      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12127    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12128      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12129
12130    warp_to = 1;
12131    warp_to_win = bd->zone->container->win;
12132    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12133    if (!warp_timer)
12134      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12135    return 1;
12136 }
12137
12138 EAPI void
12139 e_border_comp_hidden_set(E_Border *bd,
12140                          Eina_Bool hidden)
12141 {
12142    E_Border *tmp;
12143    Eina_List *l;
12144
12145    E_OBJECT_CHECK(bd);
12146    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12147
12148    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12149      {
12150        if (hidden)
12151          ecore_x_window_hide(tmp->win);
12152        else
12153          ecore_x_window_show(tmp->win);
12154      }
12155
12156    if (bd->comp_hidden == hidden) return;
12157
12158    bd->comp_hidden = hidden;
12159
12160    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12161      {
12162         ecore_x_composite_window_events_disable(bd->win);
12163         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12164      }
12165    else
12166      {
12167         _e_border_shape_input_rectangle_set(bd);
12168         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12169      }
12170 }
12171
12172 EAPI void
12173 e_border_tmp_input_hidden_push(E_Border *bd)
12174 {
12175    E_Border *tmp;
12176    Eina_List *l;
12177
12178    E_OBJECT_CHECK(bd);
12179    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12180
12181    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12182      e_border_tmp_input_hidden_push(tmp);
12183
12184    bd->tmp_input_hidden++;
12185    if (bd->tmp_input_hidden != 1) return;
12186
12187    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12188      {
12189         ecore_x_composite_window_events_disable(bd->win);
12190         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12191      }
12192    else
12193      {
12194         _e_border_shape_input_rectangle_set(bd);
12195         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12196      }
12197 }
12198
12199 EAPI void
12200 e_border_tmp_input_hidden_pop(E_Border *bd)
12201 {
12202    E_Border *tmp;
12203    Eina_List *l;
12204
12205    E_OBJECT_CHECK(bd);
12206    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12207
12208    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12209      e_border_tmp_input_hidden_pop(tmp);
12210
12211    bd->tmp_input_hidden--;
12212    if (bd->tmp_input_hidden != 0) return;
12213
12214    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12215      {
12216         ecore_x_composite_window_events_disable(bd->win);
12217         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12218      }
12219    else
12220      {
12221         _e_border_shape_input_rectangle_set(bd);
12222         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12223      }
12224 }
12225
12226 EAPI void
12227 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
12228 {
12229    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
12230        ((bd->parent) &&
12231         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
12232          ((bd->parent->focused) &&
12233           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
12234        (just_do_it))
12235      {
12236         if (bd->iconic)
12237           {
12238              if (e_config->clientlist_warp_to_iconified_desktop == 1)
12239                e_desk_show(bd->desk);
12240              
12241              if (!bd->lock_user_iconify)
12242                e_border_uniconify(bd);
12243           }
12244         if ((!bd->iconic) && (!bd->sticky))
12245           e_desk_show(bd->desk);
12246         if (!bd->lock_user_stacking) e_border_raise(bd);
12247         if (!bd->lock_focus_out)
12248           {
12249              /* XXX ooffice does send this request for
12250               config dialogs when the main window gets focus.
12251               causing the pointer to jump back and forth.  */
12252              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
12253                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
12254                ecore_x_pointer_warp(bd->zone->container->win,
12255                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
12256              e_border_focus_set(bd, 1, 1);
12257           }
12258      }
12259 }
12260 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/