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