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