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