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