Modify to compare angle that comming from client by rotation done message with BORDER...
[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->client.e.state.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         Eina_Bool is_screen_locked = EINA_FALSE;
8037
8038         if ((rot.vkbd != bd) && (rot.vkbd_prediction != bd) &&
8039             /* check whether virtual keyboard is visible on the zone */
8040             (_e_border_rotation_zone_vkbd_check(bd->zone)) &&
8041             /* check whether virtual keyboard belongs to this border (transient_for) */
8042             (_e_border_rotation_vkbd_transient_for_check(bd)) &&
8043             /* check rotation of the virtual keyboard */
8044             (((rot.vkbd) && (rot.vkbd->client.e.state.rot.curr != ang)) ||
8045              ((rot.vkbd_prediction) && (rot.vkbd_prediction->client.e.state.rot.curr != ang))) &&
8046             (!rot.wait_prepare_done))
8047           {
8048              ELB(ELBT_ROT, "DO VKBD ROT", bd->client.win);
8049              e_manager_comp_screen_lock(e_manager_current_get());
8050              is_screen_locked = EINA_TRUE;
8051
8052              if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8053              rot.prepare_timer = NULL;
8054
8055              if (rot.done_timer) ecore_timer_del(rot.done_timer);
8056              rot.done_timer = NULL;
8057
8058              ELB(ELBT_ROT, "send rot_change_prepare", rot.vkbd_ctrl_win);
8059              ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8060                                                            bd->zone->rot.curr,
8061                                                            EINA_FALSE, 1, 1);
8062              rot.prepare_timer = ecore_timer_add(4.0f,
8063                                                  _e_border_rotation_change_prepare_timeout,
8064                                                  NULL);
8065              rot.wait_prepare_done = EINA_TRUE;
8066           }
8067
8068         bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8069         bd->client.e.state.rot.curr = ang;
8070         bd->client.e.state.rot.wait_for_done = 1;
8071
8072         diff = bd->client.e.state.rot.curr - bd->client.e.state.rot.prev;
8073         if ((diff == 180) || (diff == -180))
8074           resize = EINA_FALSE;
8075
8076         /* Check if it has size hint, full size or not, and needs to resize.
8077          * Under the below condition, replace width value with height.
8078          */
8079         if ((!hint) && (!REGION_EQUAL_TO_ZONE(bd, bd->zone)) && (resize))
8080           {
8081              x = bd->x;  y = bd->y;
8082              w = bd->w;  h = bd->h;
8083
8084              if (w == h)
8085                resize = EINA_FALSE;
8086              else
8087                {
8088                   w = bd->h;
8089                   h = bd->w;
8090
8091                   _e_border_move_resize_internal(bd, x, y, w, h,
8092                                                  EINA_TRUE, EINA_FALSE);
8093                }
8094           }
8095
8096         /* hack ... */
8097         if (bd->client.e.state.rot.app_set) resize = EINA_FALSE;
8098
8099         E_Border_Rotation_Info *info = NULL;
8100         info = E_NEW(E_Border_Rotation_Info, 1);
8101         if (info)
8102           {
8103              if (!is_screen_locked)
8104                e_manager_comp_screen_lock(e_manager_current_get());
8105
8106              info->bd = bd;
8107              info->ang = ang;
8108              info->x = x; info->y = y;
8109              info->w = w; info->h = h;
8110              info->win_resize = resize;
8111              rot.list = eina_list_append(rot.list, info);
8112
8113              if (info->win_resize)
8114                bd->client.e.state.rot.pending_change_request = 1;
8115
8116              ELBF(ELBT_ROT, 1, info->bd->client.win,
8117                   "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
8118                   info->ang, info->win_resize, info->w, info->h);
8119
8120              ecore_x_e_window_rotation_change_prepare_send
8121                 (info->bd->client.win, info->ang,
8122                  info->win_resize, info->w, info->h);
8123
8124              if (!info->bd->client.e.state.rot.pending_change_request)
8125                {
8126                   ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
8127                   ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
8128                                                                 info->ang);
8129                }
8130
8131              if (rot.done_timer)
8132                ecore_timer_del(rot.done_timer);
8133              rot.done_timer = ecore_timer_add(4.0f,
8134                                               _e_border_rotation_change_done_timeout,
8135                                               NULL);
8136           }
8137      }
8138    return EINA_TRUE;
8139 }
8140
8141 static Eina_Bool
8142 _e_border_rotation_zone_check(E_Zone *zone)
8143 {
8144    Eina_Bool wait = EINA_FALSE;
8145    E_Border_List *l = NULL;
8146    E_Border *bd = NULL;
8147
8148    if (!e_config->wm_win_rotation) return EINA_FALSE;
8149
8150    l = e_container_border_list_last(zone->container);
8151    if (!l) return EINA_FALSE;
8152    while ((bd = e_container_border_list_prev(l)))
8153      {
8154         if ((!bd) || (e_object_is_del(E_OBJECT(bd))) ||
8155             (!bd->visible) || (bd->zone != zone) ||
8156             (!E_INTERSECTS(zone->x, zone->y, zone->w, zone->h,
8157                            bd->x, bd->y, bd->w, bd->h))) continue;
8158
8159         if (((rot.vkbd) && (rot.vkbd == bd)) ||
8160             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)) ||
8161             ((REGION_EQUAL_TO_ZONE(bd, zone)) &&
8162              (bd->client.e.state.rot.preferred_rot != -1))) continue;
8163
8164         if (_e_border_rotation_border_check(bd, zone->rot.curr))
8165           {
8166              wait = EINA_TRUE;
8167              break;
8168           }
8169      }
8170    if (l) e_container_border_list_free(l);
8171
8172    return wait;
8173 }
8174
8175 // check if border is rotatable in ang.
8176 static Eina_Bool
8177 _e_border_rotation_border_check(E_Border *bd, int ang)
8178 {
8179    Eina_Bool wait = EINA_FALSE;
8180
8181    if (!bd) return wait;
8182
8183    if (((bd->client.e.state.rot.support) || (bd->client.e.state.rot.app_set)) &&
8184        /* basically WM allows only fullscreen window to rotate */
8185        ((REGION_EQUAL_TO_ZONE(bd, bd->zone)) ||
8186         /* we don't like this kind of code.
8187          * it means that the WM also allows non-fullscreen window to rotate if it sets geom hint.
8188          * such as large editable window.
8189          */
8190         ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE) && (bd->client.e.state.rot.geom_hint)) ||
8191         /* and floating mode window is also rotatable */
8192         (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) &&
8193        (bd->client.e.state.rot.preferred_rot == -1))
8194      {
8195         unsigned int i;
8196
8197         if (bd->client.e.state.rot.app_set)
8198           {
8199              if (bd->client.e.state.rot.available_rots &&
8200                  bd->client.e.state.rot.count)
8201                {
8202                   Eina_Bool found = EINA_FALSE;
8203                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8204                     {
8205                        if (bd->client.e.state.rot.available_rots[i] == ang)
8206                          {
8207                             found = EINA_TRUE;
8208                          }
8209                     }
8210                   if ((found) && (ang != bd->client.e.state.rot.curr))
8211                     {
8212                        wait = EINA_TRUE;
8213                     }
8214                   else
8215                     {
8216                        ELB(ELBT_ROT, "ROT CANCEL for preferred rot", bd->client.win);
8217                        wait = EINA_FALSE;
8218                     }
8219                }
8220           }
8221         else
8222           {
8223              ELB(ELBT_ROT, "DO ROT", 0);
8224              wait = EINA_TRUE;
8225           }
8226      }
8227
8228    return wait;
8229 }
8230
8231 /* check whether virtual keyboard is visible on the zone */
8232 static Eina_Bool
8233 _e_border_rotation_zone_vkbd_check(E_Zone *zone)
8234 {
8235    if (!e_config->wm_win_rotation) return EINA_FALSE;
8236
8237    if ((rot.vkbd_ctrl_win) &&
8238        (rot.vkbd) &&
8239        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8240        (rot.vkbd->visible) &&
8241        (rot.vkbd->zone == zone) &&
8242        (E_INTERSECTS(zone->x, zone->y,
8243                      zone->w, zone->h,
8244                      rot.vkbd->x, rot.vkbd->y,
8245                      rot.vkbd->w, rot.vkbd->h)))
8246      {
8247         return EINA_TRUE;
8248      }
8249    return EINA_FALSE;
8250 }
8251
8252 /* check whether border is parent of the virtual keyboard */
8253 static Eina_Bool
8254 _e_border_rotation_vkbd_transient_for_check(E_Border *bd)
8255 {
8256    if (!e_config->wm_win_rotation) return EINA_FALSE;
8257
8258    if (rot.vkbd_ctrl_win)
8259      {
8260         if ((rot.vkbd) && (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8261             (rot.vkbd != bd))
8262           {
8263              if (rot.vkbd->parent == bd)
8264                return EINA_TRUE;
8265           }
8266
8267         if ((rot.vkbd_prediction) && (!e_object_is_del(E_OBJECT(rot.vkbd_prediction))) &&
8268             (rot.vkbd_prediction != bd))
8269           {
8270              if (rot.vkbd_prediction == bd)
8271                return EINA_TRUE;
8272           }
8273      }
8274
8275    return EINA_FALSE;
8276 }
8277
8278 // check if bd's parent is rotatable.
8279 static Eina_Bool
8280 _e_border_rotation_transient_for_check(E_Border *bd, int ang)
8281 {
8282    Eina_Bool ret = EINA_FALSE;
8283
8284    if (!e_config->wm_win_rotation) return EINA_FALSE;
8285    if (!bd) return EINA_FALSE;
8286
8287    if (!bd->parent) ret = EINA_TRUE;
8288    else
8289      {
8290         if (_e_border_rotation_border_check(bd->parent, ang))
8291           ret = EINA_TRUE;
8292      }
8293
8294    return ret;
8295 }
8296
8297 static Eina_Bool
8298 _e_border_rotation_list_add(E_Zone *zone, Eina_Bool without_vkbd)
8299 {
8300    Eina_Bool wait = EINA_FALSE;
8301    E_Border_List *l = NULL;
8302    Eina_List *nl = NULL;
8303    E_Border *bd = NULL;
8304    E_Border_Rotation_Info *info = NULL;
8305
8306    if (!e_config->wm_win_rotation) return EINA_FALSE;
8307
8308    l = e_container_border_list_last(zone->container);
8309    if (!l) return EINA_FALSE;
8310    while ((bd = e_container_border_list_prev(l)))
8311      {
8312         if ((!bd) || (e_object_is_del(E_OBJECT(bd)))) continue;
8313
8314         if ((without_vkbd) &&
8315             (((rot.vkbd) && (rot.vkbd == bd)) ||
8316              ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))) continue;
8317
8318         if ((bd->visible) &&
8319             ((bd->client.e.state.rot.support) || (bd->client.e.state.rot.app_set)) &&
8320             (bd->zone == zone) &&
8321             (E_INTERSECTS(zone->x, zone->y, zone->w, zone->h,
8322                           bd->x, bd->y, bd->w, bd->h)))
8323           {
8324              // check if this window is available to be rotate.
8325              if ((bd->client.e.state.rot.app_set) &&
8326                  (bd->client.e.state.rot.preferred_rot != -1)) continue;
8327
8328              /* check list of available rotations */
8329              int ang = zone->rot.curr;
8330              if (bd->client.e.state.rot.app_set)
8331                {
8332                   ang = _e_border_rotation_get(bd, ang);
8333                   ELBF(ELBT_ROT, 0, bd->client.win, "returned ang:%d", ang);
8334                }
8335
8336              /* skip same angle */
8337              if (bd->client.e.state.rot.curr == ang)
8338                {
8339                   ELBF(ELBT_ROT, 0, bd->client.win, "SKIP ang:%d", ang);
8340                   continue;
8341                }
8342              else
8343                {
8344                   ELBF(ELBT_ROT, 0, bd->client.win, "ADD ROT_LIST curr:%d != ang:%d",
8345                        bd->client.e.state.rot.curr, ang);
8346                }
8347
8348              bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8349              bd->client.e.state.rot.curr = ang;
8350              bd->client.e.state.rot.wait_for_done = 1;
8351
8352              info = E_NEW(E_Border_Rotation_Info, 1);
8353              if (info)
8354                {
8355                   info->bd = bd;
8356                   info->ang = ang;
8357                   info->x = bd->x; info->y = bd->y;
8358                   info->w = bd->w; info->h = bd->h;
8359                   info->win_resize = EINA_FALSE;
8360                   nl = eina_list_append(nl, info);
8361                }
8362
8363              if (REGION_EQUAL_TO_ZONE(bd, zone))
8364                {
8365                   wait = EINA_TRUE; // for the maximized window
8366                }
8367              else
8368                {
8369                   int diff = bd->client.e.state.rot.curr - bd->client.e.state.rot.prev;
8370                   int x, y, w, h;
8371                   Eina_Bool resize = EINA_TRUE;
8372                   if ((diff == 180) || (diff == -180))
8373                     resize = EINA_FALSE;
8374
8375                   Eina_Bool move = EINA_TRUE;
8376                   Eina_Bool hint = EINA_FALSE;
8377                   hint = _e_border_rotation_geom_get(bd, zone, zone->rot.curr, &x, &y, &w, &h, &move);
8378                   if (hint)
8379                     _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
8380                   else
8381                     {
8382                        x = bd->x; y = bd->y;
8383                        w = bd->w; h = bd->h;
8384                        if (resize)
8385                          {
8386                             if (w == h)
8387                               resize = EINA_FALSE;
8388                             else
8389                               {
8390                                  // swap width and height and resize border
8391                                  w = bd->h;
8392                                  h = bd->w;
8393
8394                                  _e_border_move_resize_internal(bd, x, y, w, h,
8395                                                                 EINA_TRUE, EINA_TRUE);
8396                               }
8397                          }
8398                     }
8399
8400                   if (info)
8401                     {
8402                        info->x = x; info->y = y;
8403                        info->w = w; info->h = h;
8404                        info->win_resize = resize;
8405                     }
8406
8407                   if (resize)
8408                     bd->client.e.state.rot.pending_change_request = 1;
8409
8410                   wait = EINA_TRUE;
8411                }
8412           }
8413      }
8414
8415    if (l) e_container_border_list_free(l);
8416
8417    if (nl)
8418      {
8419         // clear previous list
8420         EINA_LIST_FREE(rot.list, info)
8421           {
8422              E_FREE(info);
8423           }
8424         rot.list = nl;
8425      }
8426
8427    return wait;
8428 }
8429
8430 static Eina_Bool
8431 _e_border_cb_window_configure(void *data    __UNUSED__,
8432                               int   ev_type __UNUSED__,
8433                               void         *ev)
8434 {
8435    Ecore_X_Event_Window_Configure *e = ev;
8436    if (!e) return ECORE_CALLBACK_PASS_ON;
8437    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8438
8439    E_Border *bd = e_border_find_by_client_window(e->win);
8440    if (!bd) return ECORE_CALLBACK_PASS_ON;
8441
8442    if (bd->client.e.state.rot.pending_change_request)
8443      {
8444         if ((e->w == bd->w) && (e->h == bd->h))
8445           {
8446              ELBF(ELBT_ROT, 0, bd->client.win,
8447                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
8448                   bd->client.e.state.rot.curr,
8449                   bd->w, bd->h);
8450
8451              bd->client.e.state.rot.pending_change_request = 0;
8452
8453              ecore_x_e_window_rotation_change_request_send(bd->client.win,
8454                                                            bd->client.e.state.rot.curr);
8455           }
8456      }
8457    return ECORE_CALLBACK_PASS_ON;
8458 }
8459
8460 static Eina_Bool
8461 _e_border_rotation_geom_get(E_Border  *bd,
8462                             E_Zone    *zone,
8463                             int        ang,
8464                             int       *x,
8465                             int       *y,
8466                             int       *w,
8467                             int       *h,
8468                             Eina_Bool *move)
8469 {
8470    if (!e_config->wm_win_rotation) return EINA_FALSE;
8471
8472    Eina_Bool res = EINA_FALSE;
8473    Eina_Bool _move = EINA_TRUE;
8474    int _x = bd->x;
8475    int _y = bd->y;
8476    int _w = bd->w;
8477    int _h = bd->h;
8478
8479    if (x) *x = bd->x;
8480    if (y) *y = bd->y;
8481    if (w) *w = bd->w;
8482    if (h) *h = bd->h;
8483    if (move) *move = EINA_TRUE;
8484
8485    if (bd->client.e.state.rot.geom_hint)
8486      {
8487         switch (ang)
8488           {
8489            case   0:
8490               _w = bd->client.e.state.rot.geom[0].w;
8491               _h = bd->client.e.state.rot.geom[0].h;
8492               if (_w == 0) _w = bd->w;
8493               if (_h == 0) _h = bd->h;
8494               _x = 0; _y = zone->h - _h;
8495               break;
8496            case  90:
8497               _w = bd->client.e.state.rot.geom[1].w;
8498               _h = bd->client.e.state.rot.geom[1].h;
8499               if (_w == 0) _w = bd->w;
8500               if (_h == 0) _h = bd->h;
8501               _x = zone->w - _w; _y = 0;
8502               break;
8503            case 180:
8504               _w = bd->client.e.state.rot.geom[2].w;
8505               _h = bd->client.e.state.rot.geom[2].h;
8506               if (_w == 0) _w = bd->w;
8507               if (_h == 0) _h = bd->h;
8508               _x = 0; _y = 0;
8509               break;
8510            case 270:
8511               _w = bd->client.e.state.rot.geom[3].w;
8512               _h = bd->client.e.state.rot.geom[3].h;
8513               if (_w == 0) _w = bd->w;
8514               if (_h == 0) _h = bd->h;
8515               _x = 0; _y = 0;
8516               break;
8517           }
8518
8519         if (x) *x = _x;
8520         if (y) *y = _y;
8521         if (w) *w = _w;
8522         if (h) *h = _h;
8523
8524         if (!((rot.vkbd) && (rot.vkbd == bd)))
8525           {
8526              if (x) *x = bd->x;
8527              if (y) *y = bd->y;
8528              if (move) *move = EINA_FALSE;
8529           }
8530
8531         res = EINA_TRUE;
8532      }
8533
8534    if (res)
8535      {
8536         _x = 0; _y = 0; _w = 0; _h = 0;
8537         if (x) _x = *x;
8538         if (y) _y = *y;
8539         if (w) _w = *w;
8540         if (h) _h = *h;
8541         if (move) _move = *move;
8542
8543         ELBF(ELBT_ROT, 1, bd->client.win,
8544              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
8545              ang, _x, _y, _w, _h, _move);
8546      }
8547
8548    return res;
8549 }
8550 #endif
8551
8552 static Eina_Bool
8553 _e_border_post_move_resize_job(void *data)
8554 {
8555    E_Border *bd;
8556
8557    bd = (E_Border *)data;
8558    if (bd->post_move)
8559      {
8560         E_Border *tmp;
8561         Eina_List *l;
8562
8563         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
8564           ecore_x_window_move(tmp->win,
8565                               bd->x +
8566                               bd->client_inset.l +
8567                               bd->fx.x +
8568                               tmp->client.e.state.video_position.x,
8569                               bd->y +
8570                               bd->client_inset.t +
8571                               bd->fx.y +
8572                               tmp->client.e.state.video_position.y);
8573      }
8574    if (bd->client.e.state.video)
8575      {
8576         E_Border *parent;
8577
8578         parent = bd->client.e.state.video_parent_border;
8579         ecore_x_window_move(bd->win,
8580                             parent->x +
8581                             parent->client_inset.l +
8582                             parent->fx.x +
8583                             bd->client.e.state.video_position.x,
8584                             parent->y +
8585                             parent->client_inset.t +
8586                             parent->fx.y +
8587                             bd->client.e.state.video_position.y);
8588      }
8589    else if ((bd->post_move) && (bd->post_resize))
8590      {
8591         ecore_x_window_move_resize(bd->win,
8592                                    bd->x + bd->fx.x,
8593                                    bd->y + bd->fx.y,
8594                                    bd->w, bd->h);
8595      }
8596    else if (bd->post_move)
8597      {
8598         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
8599      }
8600    else if (bd->post_resize)
8601      {
8602         ecore_x_window_resize(bd->win, bd->w, bd->h);
8603      }
8604
8605    if (bd->client.e.state.video)
8606      {
8607         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
8608                 bd->win,
8609                 bd->client.e.state.video_parent_border->x +
8610                 bd->client.e.state.video_parent_border->client_inset.l +
8611                 bd->client.e.state.video_parent_border->fx.x +
8612                 bd->client.e.state.video_position.x,
8613                 bd->client.e.state.video_parent_border->y +
8614                 bd->client.e.state.video_parent_border->client_inset.t +
8615                 bd->client.e.state.video_parent_border->fx.y +
8616                 bd->client.e.state.video_position.y,
8617                 bd->w, bd->h);
8618      }
8619
8620    if (bd->post_show)
8621      {
8622         if (bd->visible)
8623           {
8624              bd->post_job = NULL;
8625              _e_border_show(bd);
8626           }
8627      }
8628    bd->post_show = 0;
8629    bd->post_move = 0;
8630    bd->post_resize = 0;
8631    bd->post_job = NULL;
8632    return ECORE_CALLBACK_CANCEL;
8633 }
8634
8635 static void
8636 _e_border_container_layout_hook(E_Container *con)
8637 {
8638    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
8639 }
8640
8641 static void
8642 _e_border_eval0(E_Border *bd)
8643 {
8644    int change_urgent = 0;
8645    int rem_change = 0;
8646 #ifdef _F_USE_DESK_WINDOW_PROFILE_
8647    Eina_Bool need_desk_set = EINA_FALSE;
8648 #endif
8649 #ifdef _F_ZONE_WINDOW_ROTATION_
8650    Eina_Bool need_rotation_set = EINA_FALSE;
8651
8652    if ((e_config->wm_win_rotation) &&
8653        (bd->client.icccm.fetch.transient_for))
8654      {
8655         if (((rot.vkbd) && (rot.vkbd == bd)) ||
8656             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
8657           {
8658              need_rotation_set = EINA_TRUE;
8659              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
8660           }
8661      }
8662 #endif
8663
8664    if (e_object_is_del(E_OBJECT(bd)))
8665      {
8666         CRI("_e_border_eval(%p) with deleted border!\n", bd);
8667         bd->changed = 0;
8668         return;
8669      }
8670
8671    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
8672
8673    bd->changes.border = 0;
8674
8675    /* fetch any info queued to be fetched */
8676    if (bd->client.netwm.fetch.state)
8677      {
8678         e_hints_window_state_get(bd);
8679         bd->client.netwm.fetch.state = 0;
8680         rem_change = 1;
8681      }
8682    if (bd->client.icccm.fetch.client_leader)
8683      {
8684         /* TODO: What do to if the client leader isn't mapped yet? */
8685         E_Border *bd_leader = NULL;
8686
8687         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
8688         if (bd->client.icccm.client_leader)
8689           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
8690         if (bd->leader)
8691           {
8692              if (bd->leader != bd_leader)
8693                {
8694                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
8695                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
8696                   bd->leader = NULL;
8697                }
8698              else
8699                bd_leader = NULL;
8700           }
8701         /* If this border is the leader of the group, don't register itself */
8702         if ((bd_leader) && (bd_leader != bd))
8703           {
8704              bd_leader->group = eina_list_append(bd_leader->group, bd);
8705              bd->leader = bd_leader;
8706              /* Only set the window modal to the leader it there is no parent */
8707              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
8708                  ((!bd->parent) || (bd->parent->modal != bd)))
8709                {
8710                   bd->leader->modal = bd;
8711                   if (bd->leader->focused)
8712                     e_border_focus_set(bd, 1, 1);
8713                   else
8714                     {
8715                        Eina_List *l;
8716                        E_Border *child;
8717
8718                        EINA_LIST_FOREACH(bd->leader->group, l, child)
8719                          {
8720                             if ((child != bd) && (child->focused))
8721                               e_border_focus_set(bd, 1, 1);
8722                          }
8723                     }
8724                }
8725           }
8726         bd->client.icccm.fetch.client_leader = 0;
8727         rem_change = 1;
8728      }
8729    if (bd->client.icccm.fetch.title)
8730      {
8731         char *title = ecore_x_icccm_title_get(bd->client.win);
8732         eina_stringshare_replace(&bd->client.icccm.title, title);
8733         if (title) free(title);
8734
8735         if (bd->bg_object)
8736           edje_object_part_text_set(bd->bg_object, "e.text.title",
8737                                     bd->client.icccm.title);
8738         bd->client.icccm.fetch.title = 0;
8739         rem_change = 1;
8740      }
8741    if (bd->client.netwm.fetch.name)
8742      {
8743         char *name;
8744         ecore_x_netwm_name_get(bd->client.win, &name);
8745         eina_stringshare_replace(&bd->client.netwm.name, name);
8746         if (name) free(name);
8747
8748         if (bd->bg_object)
8749           edje_object_part_text_set(bd->bg_object, "e.text.title",
8750                                     bd->client.netwm.name);
8751         bd->client.netwm.fetch.name = 0;
8752         rem_change = 1;
8753      }
8754    if (bd->client.icccm.fetch.name_class)
8755      {
8756         const char *pname, *pclass;
8757         char *nname, *nclass;
8758
8759         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
8760         pname = bd->client.icccm.name;
8761         pclass = bd->client.icccm.class;
8762         bd->client.icccm.name = eina_stringshare_add(nname);
8763         bd->client.icccm.class = eina_stringshare_add(nclass);
8764         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
8765           e_bindings_mapping_change_enable(EINA_FALSE);
8766 #ifdef _F_ZONE_WINDOW_ROTATION_
8767         if (e_config->wm_win_rotation)
8768           {
8769              if ((bd->client.icccm.name) && (bd->client.icccm.class))
8770                {
8771                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
8772                       (!strcmp(bd->client.icccm.class, "ISF")))
8773                     {
8774                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
8775                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
8776                        rot.vkbd = bd;
8777                     }
8778                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
8779                            (!strcmp(bd->client.icccm.class, "ISF")))
8780                     {
8781                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
8782                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
8783                        rot.vkbd_prediction = bd;
8784                     }
8785                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
8786                            (!strcmp(bd->client.icccm.class, "ISF")))
8787                     {
8788                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
8789                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
8790                     }
8791                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
8792                            (!strcmp(bd->client.icccm.class, "ISF")))
8793                     {
8794                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
8795                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
8796                     }
8797                }
8798           }
8799 #endif
8800         if (nname) free(nname);
8801         if (nclass) free(nclass);
8802
8803         if (!((bd->client.icccm.name == pname) &&
8804               (bd->client.icccm.class == pclass)))
8805           bd->changes.icon = 1;
8806
8807         if (pname) eina_stringshare_del(pname);
8808         if (pclass) eina_stringshare_del(pclass);
8809         bd->client.icccm.fetch.name_class = 0;
8810         bd->changes.icon = 1;
8811         rem_change = 1;
8812      }
8813    if (bd->client.icccm.fetch.state)
8814      {
8815         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
8816         bd->client.icccm.fetch.state = 0;
8817         rem_change = 1;
8818      }
8819    if (bd->client.e.fetch.state)
8820      {
8821         e_hints_window_e_state_get(bd);
8822         bd->client.e.fetch.state = 0;
8823         rem_change = 1;
8824      }
8825 #ifdef _F_USE_DESK_WINDOW_PROFILE_
8826    if (bd->client.e.fetch.profile_list)
8827      {
8828         const char **profiles = NULL;
8829         const char *str;
8830         int num, i;
8831
8832         if (bd->client.e.state.profile)
8833           eina_stringshare_del(bd->client.e.state.profile);
8834         EINA_LIST_FREE(bd->client.e.state.profiles, str)
8835           {
8836              if (str) eina_stringshare_del(str);
8837           }
8838         bd->client.e.state.profile = NULL;
8839         bd->client.e.state.profiles = NULL;
8840         bd->client.e.state.profile_list = 0;
8841
8842         if (ecore_x_e_window_profile_list_get(bd->client.win,
8843                                               &profiles, &num))
8844           {
8845              bd->client.e.state.profile_list = 1;
8846              for (i = 0; i < num; i++)
8847                {
8848                   str = eina_stringshare_add(profiles[i]);
8849                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
8850                }
8851
8852              /* We should set desk to contain given border after creating E_BORDER_ADD event.
8853               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
8854               */
8855              need_desk_set = EINA_TRUE;
8856           }
8857         else
8858           {
8859              if (strcmp(bd->desk->window_profile,
8860                         e_config->desktop_default_window_profile) != 0)
8861                {
8862                   ecore_x_e_window_profile_set(bd->client.win,
8863                                                bd->desk->window_profile);
8864                }
8865           }
8866
8867         if (profiles)
8868           free(profiles);
8869
8870         bd->client.e.fetch.profile_list = 0;
8871      }
8872 #endif
8873 #ifdef _F_ZONE_WINDOW_ROTATION_
8874    if ((e_config->wm_win_rotation) &&
8875        (bd->client.e.fetch.rot.support))
8876      {
8877         int ret = 0;
8878         unsigned int support = 0;
8879
8880         ret = ecore_x_window_prop_card32_get
8881           (bd->client.win,
8882           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
8883           &support, 1);
8884
8885         bd->client.e.state.rot.support = 0;
8886         if ((ret == 1) && (support == 1))
8887           bd->client.e.state.rot.support = 1;
8888
8889         if (bd->client.e.state.rot.support)
8890           need_rotation_set = EINA_TRUE;
8891
8892         bd->client.e.fetch.rot.support = 0;
8893      }
8894    if ((e_config->wm_win_rotation) &&
8895        (bd->client.e.fetch.rot.geom_hint))
8896      {
8897         Eina_Rectangle r[4];
8898         int i, x, y, w, h;
8899         bd->client.e.state.rot.geom_hint = 0;
8900         for (i = 0; i < 4; i++)
8901           {
8902              r[i].x = bd->client.e.state.rot.geom[i].x;
8903              r[i].y = bd->client.e.state.rot.geom[i].y;
8904              r[i].w = bd->client.e.state.rot.geom[i].w;
8905              r[i].h = bd->client.e.state.rot.geom[i].h;
8906
8907              bd->client.e.state.rot.geom[i].x = 0;
8908              bd->client.e.state.rot.geom[i].y = 0;
8909              bd->client.e.state.rot.geom[i].w = 0;
8910              bd->client.e.state.rot.geom[i].h = 0;
8911           }
8912
8913         for (i = 0; i < 4; i++)
8914           {
8915              x = 0; y = 0; w = 0; h = 0;
8916              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
8917                {
8918                   bd->client.e.state.rot.geom_hint = 1;
8919                   bd->client.e.state.rot.geom[i].x = x;
8920                   bd->client.e.state.rot.geom[i].y = y;
8921                   bd->client.e.state.rot.geom[i].w = w;
8922                   bd->client.e.state.rot.geom[i].h = h;
8923
8924                   if (!((r[i].x == x) && (r[i].y == y) &&
8925                         (r[i].w == w) && (r[i].h == h)))
8926                     {
8927                        need_rotation_set = EINA_TRUE;
8928                     }
8929                }
8930           }
8931         bd->client.e.fetch.rot.geom_hint = 0;
8932      }
8933    if ((e_config->wm_win_rotation) &&
8934        (bd->client.e.fetch.rot.app_set))
8935      {
8936         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
8937         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
8938         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
8939
8940         if (_prev_app_set != bd->client.e.state.rot.app_set)
8941           need_rotation_set = EINA_TRUE;
8942
8943         bd->client.e.fetch.rot.app_set = 0;
8944      }
8945    if ((e_config->wm_win_rotation) &&
8946        (bd->client.e.fetch.rot.preferred_rot))
8947      {
8948         int r = 0, _prev_preferred_rot;
8949         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
8950         bd->client.e.state.rot.preferred_rot = -1;
8951         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
8952           {
8953              bd->client.e.state.rot.preferred_rot = r;
8954              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
8955           }
8956         else
8957           {
8958              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
8959           }
8960
8961         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
8962           need_rotation_set = EINA_TRUE;
8963
8964         bd->client.e.fetch.rot.preferred_rot = 0;
8965      }
8966    if ((e_config->wm_win_rotation) &&
8967        (bd->client.e.fetch.rot.available_rots))
8968      {
8969         Eina_Bool res, diff = EINA_FALSE;
8970         int *rots = NULL;
8971         unsigned int count = 0, i = 0;
8972         int _prev_rots[4] = { -1, };
8973
8974         if (bd->client.e.state.rot.available_rots)
8975           {
8976              memcpy(_prev_rots,
8977                     bd->client.e.state.rot.available_rots,
8978                     (sizeof(int) * bd->client.e.state.rot.count));
8979
8980              E_FREE(bd->client.e.state.rot.available_rots);
8981           }
8982
8983         bd->client.e.state.rot.count = 0;
8984
8985         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
8986                                                                 &rots, &count);
8987         if ((res) && (count > 0) && (rots))
8988           {
8989              bd->client.e.state.rot.available_rots = rots;
8990              bd->client.e.state.rot.count = count;
8991
8992              for (i = 0; i < count; i++)
8993                {
8994                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
8995                   if ((!diff) && (_prev_rots[i] != rots[i]))
8996                     {
8997                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
8998                             count, i, _prev_rots[i], rots[i]);
8999                        diff = EINA_TRUE;
9000                     }
9001                }
9002           }
9003         else
9004           {
9005              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9006              diff = EINA_TRUE;
9007           }
9008
9009         if (diff) need_rotation_set = EINA_TRUE;
9010         bd->client.e.fetch.rot.available_rots = 0;
9011      }
9012 #endif
9013    if (bd->client.netwm.fetch.type)
9014      {
9015         e_hints_window_type_get(bd);
9016         if ((!bd->lock_border) || (!bd->client.border.name))
9017           bd->client.border.changed = 1;
9018
9019         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9020           {
9021              if (!bd->client.netwm.state.skip_pager)
9022                {
9023                   bd->client.netwm.state.skip_pager = 1;
9024                   bd->client.netwm.update.state = 1;
9025                }
9026              if (!bd->client.netwm.state.skip_taskbar)
9027                {
9028                   bd->client.netwm.state.skip_taskbar = 1;
9029                   bd->client.netwm.update.state = 1;
9030                }
9031           }
9032         bd->client.netwm.fetch.type = 0;
9033      }
9034    if (bd->client.icccm.fetch.machine)
9035      {
9036         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9037
9038         if ((!machine) && (bd->client.icccm.client_leader))
9039           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9040
9041         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9042         if (machine) free(machine);
9043
9044         bd->client.icccm.fetch.machine = 0;
9045         rem_change = 1;
9046      }
9047    if (bd->client.icccm.fetch.command)
9048      {
9049         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9050           {
9051              int i;
9052
9053              for (i = 0; i < bd->client.icccm.command.argc; i++)
9054                free(bd->client.icccm.command.argv[i]);
9055              free(bd->client.icccm.command.argv);
9056           }
9057         bd->client.icccm.command.argc = 0;
9058         bd->client.icccm.command.argv = NULL;
9059         ecore_x_icccm_command_get(bd->client.win,
9060                                   &(bd->client.icccm.command.argc),
9061                                   &(bd->client.icccm.command.argv));
9062         if ((bd->client.icccm.client_leader) &&
9063             (!bd->client.icccm.command.argv))
9064           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9065                                     &(bd->client.icccm.command.argc),
9066                                     &(bd->client.icccm.command.argv));
9067         bd->client.icccm.fetch.command = 0;
9068         rem_change = 1;
9069      }
9070    if (bd->client.icccm.fetch.hints)
9071      {
9072         Eina_Bool accepts_focus, is_urgent;
9073
9074         accepts_focus = EINA_TRUE;
9075         is_urgent = EINA_FALSE;
9076         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9077         if (ecore_x_icccm_hints_get(bd->client.win,
9078                                     &accepts_focus,
9079                                     &bd->client.icccm.initial_state,
9080                                     &bd->client.icccm.icon_pixmap,
9081                                     &bd->client.icccm.icon_mask,
9082                                     &bd->client.icccm.icon_window,
9083                                     &bd->client.icccm.window_group,
9084                                     &is_urgent))
9085           {
9086              bd->client.icccm.accepts_focus = accepts_focus;
9087              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9088                change_urgent = 1;
9089              bd->client.icccm.urgent = is_urgent;
9090
9091              /* If this is a new window, set the state as requested. */
9092              if ((bd->new_client) &&
9093                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9094                {
9095                   e_border_iconify(bd);
9096                   e_border_hide(bd, 1);
9097                }
9098           }
9099         bd->client.icccm.fetch.hints = 0;
9100         rem_change = 1;
9101      }
9102    if (bd->client.icccm.fetch.size_pos_hints)
9103      {
9104         Eina_Bool request_pos;
9105
9106         request_pos = EINA_FALSE;
9107         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9108                                              &request_pos,
9109                                              &bd->client.icccm.gravity,
9110                                              &bd->client.icccm.min_w,
9111                                              &bd->client.icccm.min_h,
9112                                              &bd->client.icccm.max_w,
9113                                              &bd->client.icccm.max_h,
9114                                              &bd->client.icccm.base_w,
9115                                              &bd->client.icccm.base_h,
9116                                              &bd->client.icccm.step_w,
9117                                              &bd->client.icccm.step_h,
9118                                              &bd->client.icccm.min_aspect,
9119                                              &bd->client.icccm.max_aspect))
9120           {
9121              bd->client.icccm.request_pos = request_pos;
9122           }
9123         else
9124           {
9125           }
9126         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9127         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9128         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9129         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9130         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9131         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9132         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9133         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9134         // if doing a resize, fix it up
9135         if (bd->resize_mode != RESIZE_NONE)
9136           {
9137              int x, y, w, h, new_w, new_h;
9138
9139              x = bd->x;
9140              y = bd->y;
9141              w = bd->w;
9142              h = bd->h;
9143              new_w = w;
9144              new_h = h;
9145              e_border_resize_limit(bd, &new_w, &new_h);
9146              if ((bd->resize_mode == RESIZE_TL) ||
9147                  (bd->resize_mode == RESIZE_L) ||
9148                  (bd->resize_mode == RESIZE_BL))
9149                x += (w - new_w);
9150              if ((bd->resize_mode == RESIZE_TL) ||
9151                  (bd->resize_mode == RESIZE_T) ||
9152                  (bd->resize_mode == RESIZE_TR))
9153                y += (h - new_h);
9154              e_border_move_resize(bd, x, y, new_w, new_h);
9155           }
9156         bd->client.icccm.fetch.size_pos_hints = 0;
9157         rem_change = 1;
9158      }
9159    if (bd->client.icccm.fetch.protocol)
9160      {
9161         int i, num;
9162         Ecore_X_WM_Protocol *proto;
9163
9164         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9165         if (proto)
9166           {
9167              for (i = 0; i < num; i++)
9168                {
9169                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9170                     bd->client.icccm.delete_request = 1;
9171                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9172                     bd->client.icccm.take_focus = 1;
9173                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9174                     bd->client.netwm.ping = 1;
9175                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9176                     {
9177                        bd->client.netwm.sync.request = 1;
9178                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9179                                                            &bd->client.netwm.sync.counter))
9180                          bd->client.netwm.sync.request = 0;
9181                     }
9182                }
9183              free(proto);
9184           }
9185         if (bd->client.netwm.ping)
9186           e_border_ping(bd);
9187         else
9188           {
9189              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9190              bd->ping_poller = NULL;
9191           }
9192         bd->client.icccm.fetch.protocol = 0;
9193      }
9194    if (bd->client.icccm.fetch.transient_for)
9195      {
9196         /* TODO: What do to if the transient for isn't mapped yet? */
9197         E_Border *bd_parent = NULL;
9198
9199         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9200         if (bd->client.icccm.transient_for)
9201           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9202         /* If we already have a parent, remove it */
9203         if (bd->parent)
9204           {
9205              if (bd_parent != bd->parent)
9206                {
9207                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9208                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9209                   bd->parent = NULL;
9210                }
9211              else
9212                bd_parent = NULL;
9213           }
9214         if ((bd_parent) && (bd_parent != bd) &&
9215             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9216           {
9217              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9218              bd->parent = bd_parent;
9219           }
9220         if (bd->parent)
9221           {
9222              e_border_layer_set(bd, bd->parent->layer);
9223              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9224                {
9225                   Ecore_X_Window_Attributes attr;
9226                   bd->parent->modal = bd;
9227                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9228                   bd->parent->saved.event_mask = attr.event_mask.mine;
9229                   bd->parent->lock_close = 1;
9230                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9231                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9232                }
9233
9234              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9235                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9236                bd->take_focus = 1;
9237           }
9238         bd->client.icccm.fetch.transient_for = 0;
9239         rem_change = 1;
9240      }
9241    if (bd->client.icccm.fetch.window_role)
9242      {
9243         char *role = ecore_x_icccm_window_role_get(bd->client.win);
9244         eina_stringshare_replace(&bd->client.icccm.window_role, role);
9245         if (role) free(role);
9246
9247         bd->client.icccm.fetch.window_role = 0;
9248         rem_change = 1;
9249      }
9250    if (bd->client.icccm.fetch.icon_name)
9251      {
9252         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
9253         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
9254         if (icon_name) free(icon_name);
9255
9256         bd->client.icccm.fetch.icon_name = 0;
9257         rem_change = 1;
9258      }
9259    if (bd->client.netwm.fetch.icon_name)
9260      {
9261         char *icon_name;
9262         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
9263         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
9264         if (icon_name) free(icon_name);
9265
9266         bd->client.netwm.fetch.icon_name = 0;
9267         rem_change = 1;
9268      }
9269    if (bd->client.netwm.fetch.icon)
9270      {
9271         int i;
9272         if (bd->client.netwm.icons)
9273           {
9274              for (i = 0; i < bd->client.netwm.num_icons; i++)
9275                {
9276                   free(bd->client.netwm.icons[i].data);
9277                   bd->client.netwm.icons[i].data = NULL;
9278                }
9279              free(bd->client.netwm.icons);
9280           }
9281         bd->client.netwm.icons = NULL;
9282         bd->client.netwm.num_icons = 0;
9283         if (ecore_x_netwm_icons_get(bd->client.win,
9284                                      &bd->client.netwm.icons,
9285                                      &bd->client.netwm.num_icons))
9286           {
9287              // unless the rest of e17 uses border icons OTHER than icon #0
9288              // then free the rest that we don't need anymore.
9289              for (i = 1; i < bd->client.netwm.num_icons; i++)
9290                {
9291                   free(bd->client.netwm.icons[i].data);
9292                   bd->client.netwm.icons[i].data = NULL;
9293                }
9294              bd->client.netwm.num_icons = 1;
9295              bd->changes.icon = 1;
9296           }
9297         bd->client.netwm.fetch.icon = 0;
9298      }
9299    if (bd->client.netwm.fetch.user_time)
9300      {
9301         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
9302         bd->client.netwm.fetch.user_time = 0;
9303      }
9304    if (bd->client.netwm.fetch.strut)
9305      {
9306         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
9307                                              &bd->client.netwm.strut.left,
9308                                              &bd->client.netwm.strut.right,
9309                                              &bd->client.netwm.strut.top,
9310                                              &bd->client.netwm.strut.bottom,
9311                                              &bd->client.netwm.strut.left_start_y,
9312                                              &bd->client.netwm.strut.left_end_y,
9313                                              &bd->client.netwm.strut.right_start_y,
9314                                              &bd->client.netwm.strut.right_end_y,
9315                                              &bd->client.netwm.strut.top_start_x,
9316                                              &bd->client.netwm.strut.top_end_x,
9317                                              &bd->client.netwm.strut.bottom_start_x,
9318                                              &bd->client.netwm.strut.bottom_end_x))
9319           {
9320              ecore_x_netwm_strut_get(bd->client.win,
9321                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
9322                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
9323
9324              bd->client.netwm.strut.left_start_y = 0;
9325              bd->client.netwm.strut.left_end_y = 0;
9326              bd->client.netwm.strut.right_start_y = 0;
9327              bd->client.netwm.strut.right_end_y = 0;
9328              bd->client.netwm.strut.top_start_x = 0;
9329              bd->client.netwm.strut.top_end_x = 0;
9330              bd->client.netwm.strut.bottom_start_x = 0;
9331              bd->client.netwm.strut.bottom_end_x = 0;
9332           }
9333         bd->client.netwm.fetch.strut = 0;
9334      }
9335    if (bd->client.qtopia.fetch.soft_menu)
9336      {
9337         e_hints_window_qtopia_soft_menu_get(bd);
9338         bd->client.qtopia.fetch.soft_menu = 0;
9339         rem_change = 1;
9340      }
9341    if (bd->client.qtopia.fetch.soft_menus)
9342      {
9343         e_hints_window_qtopia_soft_menus_get(bd);
9344         bd->client.qtopia.fetch.soft_menus = 0;
9345         rem_change = 1;
9346      }
9347    if (bd->client.vkbd.fetch.state)
9348      {
9349         e_hints_window_virtual_keyboard_state_get(bd);
9350         bd->client.vkbd.fetch.state = 0;
9351         rem_change = 1;
9352      }
9353    if (bd->client.vkbd.fetch.vkbd)
9354      {
9355         e_hints_window_virtual_keyboard_get(bd);
9356         bd->client.vkbd.fetch.vkbd = 0;
9357         rem_change = 1;
9358      }
9359    if (bd->client.illume.conformant.fetch.conformant)
9360      {
9361         bd->client.illume.conformant.conformant =
9362           ecore_x_e_illume_conformant_get(bd->client.win);
9363         bd->client.illume.conformant.fetch.conformant = 0;
9364      }
9365    if (bd->client.illume.quickpanel.fetch.state)
9366      {
9367         bd->client.illume.quickpanel.state =
9368           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
9369         bd->client.illume.quickpanel.fetch.state = 0;
9370      }
9371    if (bd->client.illume.quickpanel.fetch.quickpanel)
9372      {
9373         bd->client.illume.quickpanel.quickpanel =
9374           ecore_x_e_illume_quickpanel_get(bd->client.win);
9375         bd->client.illume.quickpanel.fetch.quickpanel = 0;
9376      }
9377    if (bd->client.illume.quickpanel.fetch.priority.major)
9378      {
9379         bd->client.illume.quickpanel.priority.major =
9380           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
9381         bd->client.illume.quickpanel.fetch.priority.major = 0;
9382      }
9383    if (bd->client.illume.quickpanel.fetch.priority.minor)
9384      {
9385         bd->client.illume.quickpanel.priority.minor =
9386           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
9387         bd->client.illume.quickpanel.fetch.priority.minor = 0;
9388      }
9389    if (bd->client.illume.quickpanel.fetch.zone)
9390      {
9391         bd->client.illume.quickpanel.zone =
9392           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
9393         bd->client.illume.quickpanel.fetch.zone = 0;
9394      }
9395    if (bd->client.illume.drag.fetch.drag)
9396      {
9397         bd->client.illume.drag.drag =
9398           ecore_x_e_illume_drag_get(bd->client.win);
9399         bd->client.illume.drag.fetch.drag = 0;
9400      }
9401    if (bd->client.illume.drag.fetch.locked)
9402      {
9403         bd->client.illume.drag.locked =
9404           ecore_x_e_illume_drag_locked_get(bd->client.win);
9405         bd->client.illume.drag.fetch.locked = 0;
9406      }
9407    if (bd->client.illume.win_state.fetch.state)
9408      {
9409         bd->client.illume.win_state.state =
9410            ecore_x_e_illume_window_state_get(bd->client.win);
9411         bd->client.illume.win_state.fetch.state = 0;
9412      }
9413    if (bd->changes.shape)
9414      {
9415         Ecore_X_Rectangle *rects;
9416         int num;
9417
9418         bd->changes.shape = 0;
9419         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
9420         if (rects)
9421           {
9422              int cw = 0, ch = 0;
9423
9424              /* This doesn't fix the race, but makes it smaller. we detect
9425               * this and if cw and ch != client w/h then mark this as needing
9426               * a shape change again to fixup next event loop.
9427               */
9428              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9429              if ((cw != bd->client.w) || (ch != bd->client.h))
9430                bd->changes.shape = 1;
9431              if ((num == 1) &&
9432                  (rects[0].x == 0) &&
9433                  (rects[0].y == 0) &&
9434                  ((int)rects[0].width == cw) &&
9435                  ((int)rects[0].height == ch))
9436                {
9437                   if (bd->client.shaped)
9438                     {
9439                        bd->client.shaped = 0;
9440                        if (!bd->bordername)
9441                          bd->client.border.changed = 1;
9442                     }
9443                }
9444              else
9445                {
9446                   if (!bd->client.shaped)
9447                     {
9448                        bd->client.shaped = 1;
9449                        if (!bd->bordername)
9450                          bd->client.border.changed = 1;
9451                     }
9452                }
9453              free(rects);
9454           }
9455         else
9456           {
9457              // FIXME: no rects i think can mean... totally empty window
9458              bd->client.shaped = 0;
9459              if (!bd->bordername)
9460                bd->client.border.changed = 1;
9461           }
9462         bd->need_shape_merge = 1;
9463      }
9464    if (bd->changes.shape_input)
9465      {
9466         Ecore_X_Rectangle *rects;
9467         int num;
9468
9469         bd->changes.shape_input = 0;
9470         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
9471         if (rects)
9472           {
9473              int cw = 0, ch = 0;
9474
9475              /* This doesn't fix the race, but makes it smaller. we detect
9476               * this and if cw and ch != client w/h then mark this as needing
9477               * a shape change again to fixup next event loop.
9478               */
9479              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9480              if ((cw != bd->client.w) || (ch != bd->client.h))
9481                bd->changes.shape_input = 1;
9482              if ((num == 1) &&
9483                  (rects[0].x == 0) &&
9484                  (rects[0].y == 0) &&
9485                  ((int)rects[0].width == cw) &&
9486                  ((int)rects[0].height == ch))
9487                {
9488                   if (bd->shaped_input)
9489                     {
9490                        bd->shaped_input = 0;
9491                        if (!bd->bordername)
9492                          bd->client.border.changed = 1;
9493                     }
9494                }
9495              else
9496                {
9497                   if (!bd->shaped_input)
9498                     {
9499                        bd->shaped_input = 1;
9500                        if (!bd->bordername)
9501                          bd->client.border.changed = 1;
9502                     }
9503                }
9504              free(rects);
9505           }
9506         else
9507           {
9508              bd->shaped_input = 1;
9509              if (!bd->bordername)
9510                bd->client.border.changed = 1;
9511           }
9512         bd->need_shape_merge = 1;
9513      }
9514    if (bd->client.mwm.fetch.hints)
9515      {
9516         int pb;
9517
9518         bd->client.mwm.exists =
9519           ecore_x_mwm_hints_get(bd->client.win,
9520                                 &bd->client.mwm.func,
9521                                 &bd->client.mwm.decor,
9522                                 &bd->client.mwm.input);
9523         pb = bd->client.mwm.borderless;
9524         bd->client.mwm.borderless = 0;
9525         if (bd->client.mwm.exists)
9526           {
9527              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
9528                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
9529                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
9530                bd->client.mwm.borderless = 1;
9531           }
9532         if (bd->client.mwm.borderless != pb)
9533           {
9534              if ((!bd->lock_border) || (!bd->client.border.name))
9535                bd->client.border.changed = 1;
9536           }
9537         bd->client.mwm.fetch.hints = 0;
9538         rem_change = 1;
9539      }
9540    if (bd->client.e.fetch.video_parent)
9541      {
9542         /* unlinking child/parent */
9543         if (bd->client.e.state.video_parent_border != NULL)
9544           {
9545              bd->client.e.state.video_parent_border->client.e.state.video_child =
9546                eina_list_remove
9547                (bd->client.e.state.video_parent_border->client.e.state.video_child,
9548                    bd);
9549           }
9550
9551         ecore_x_window_prop_card32_get(bd->client.win,
9552                                        ECORE_X_ATOM_E_VIDEO_PARENT,
9553                                        &bd->client.e.state.video_parent,
9554                                        1);
9555
9556         /* linking child/parent */
9557         if (bd->client.e.state.video_parent != 0)
9558           {
9559              E_Border *tmp;
9560              Eina_List *l;
9561
9562              EINA_LIST_FOREACH(borders, l, tmp)
9563                if (tmp->client.win == bd->client.e.state.video_parent)
9564                  {
9565                     /* fprintf(stderr, "child added to parent \\o/\n"); */
9566                     bd->client.e.state.video_parent_border = tmp;
9567                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
9568                                                                        bd);
9569                     if (bd->desk != tmp->desk)
9570                       e_border_desk_set(bd, tmp->desk);
9571                     break;
9572                  }
9573           }
9574
9575         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
9576
9577         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
9578         rem_change = 1;
9579      }
9580    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
9581      {
9582         unsigned int xy[2];
9583
9584         ecore_x_window_prop_card32_get(bd->client.win,
9585                                        ECORE_X_ATOM_E_VIDEO_POSITION,
9586                                        xy,
9587                                        2);
9588         bd->client.e.state.video_position.x = xy[0];
9589         bd->client.e.state.video_position.y = xy[1];
9590         bd->client.e.state.video_position.updated = 1;
9591         bd->client.e.fetch.video_position = 0;
9592         bd->x = bd->client.e.state.video_position.x;
9593         bd->y = bd->client.e.state.video_position.y;
9594
9595         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
9596      }
9597    if (bd->client.netwm.update.state)
9598      {
9599         e_hints_window_state_set(bd);
9600         /* Some stats might change the border, like modal */
9601         if (((!bd->lock_border) || (!bd->client.border.name)) &&
9602             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
9603           {
9604              bd->client.border.changed = 1;
9605           }
9606         if (bd->parent)
9607           {
9608              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9609                {
9610                   bd->parent->modal = bd;
9611                   if (bd->parent->focused)
9612                     e_border_focus_set(bd, 1, 1);
9613                }
9614           }
9615         else if (bd->leader)
9616           {
9617              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9618                {
9619                   bd->leader->modal = bd;
9620                   if (bd->leader->focused)
9621                     e_border_focus_set(bd, 1, 1);
9622                   else
9623                     {
9624                        Eina_List *l;
9625                        E_Border *child;
9626
9627                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9628                          {
9629                             if ((child != bd) && (child->focused))
9630                               e_border_focus_set(bd, 1, 1);
9631                          }
9632                     }
9633                }
9634           }
9635         bd->client.netwm.update.state = 0;
9636      }
9637
9638    if (bd->new_client)
9639      {
9640         E_Event_Border_Add *ev;
9641         E_Exec_Instance *inst;
9642
9643         ev = E_NEW(E_Event_Border_Add, 1);
9644         ev->border = bd;
9645         e_object_ref(E_OBJECT(bd));
9646         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
9647         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
9648
9649         if ((!bd->lock_border) || (!bd->client.border.name))
9650           bd->client.border.changed = 1;
9651
9652           {
9653              char *str = NULL;
9654
9655              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
9656                  ((bd->client.icccm.client_leader > 0) &&
9657                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
9658                 )
9659                {
9660                   if (!strncmp(str, "E_START|", 8))
9661                     {
9662                        int id;
9663
9664                        id = atoi(str + 8);
9665                        if (id > 0) bd->client.netwm.startup_id = id;
9666                     }
9667                   free(str);
9668                }
9669           }
9670         /* It's ok not to have fetch flag, should only be set on startup
9671          *     * and not changed. */
9672         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
9673           {
9674              if (bd->client.icccm.client_leader)
9675                {
9676                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
9677                     bd->client.netwm.pid = -1;
9678                }
9679              else
9680                bd->client.netwm.pid = -1;
9681           }
9682
9683         if (!bd->re_manage)
9684           {
9685              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
9686                                                         bd->client.netwm.pid);
9687              if ((inst) && (inst->used == 0))
9688                {
9689                   E_Zone *zone;
9690                   E_Desk *desk;
9691
9692                   inst->used++;
9693                   zone = e_container_zone_number_get(bd->zone->container,
9694                                                      inst->screen);
9695                   if (zone) e_border_zone_set(bd, zone);
9696                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
9697                                           inst->desk_y);
9698                   if (desk) e_border_desk_set(bd, desk);
9699                   e_exec_instance_found(inst);
9700                }
9701
9702              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
9703                {
9704                   E_Border *bdl = NULL;
9705
9706                   bdl = bd->parent;
9707                   if (!bdl)
9708                     {
9709                        if (bd->leader) bdl = bd->leader;
9710                     }
9711                   if (!bdl)
9712                     {
9713                        E_Border *child;
9714                        E_Border_List *bl;
9715
9716                        bl = e_container_border_list_first(bd->zone->container);
9717                        while ((child = e_container_border_list_next(bl)))
9718                          {
9719                             if (child == bd) continue;
9720                             if (e_object_is_del(E_OBJECT(child))) continue;
9721                             if ((bd->client.icccm.client_leader) &&
9722                                 (child->client.icccm.client_leader ==
9723                                     bd->client.icccm.client_leader))
9724                               {
9725                                  bdl = child;
9726                                  break;
9727                               }
9728                          }
9729                        e_container_border_list_free(bl);
9730                     }
9731                   if (bdl)
9732                     {
9733                        if (bdl->zone)
9734                          e_border_zone_set(bd, bdl->zone);
9735                        if (bdl->desk)
9736                          e_border_desk_set(bd, bdl->desk);
9737                        else
9738                          e_border_stick(bd);
9739                     }
9740                }
9741           }
9742      }
9743
9744 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9745    if (need_desk_set)
9746      {
9747         E_Container *con = bd->zone->container;
9748         E_Desk *desk = NULL;
9749         Eina_List *l;
9750         const char *str;
9751         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
9752           {
9753              desk = e_container_desk_window_profile_get(con, str);
9754              if (desk)
9755                {
9756                   if (bd->desk != desk)
9757                     {
9758                        bd->client.e.state.profile = eina_stringshare_add(str);
9759                        if (bd->zone != desk->zone)
9760                          e_border_zone_set(bd, desk->zone);
9761                        e_border_desk_set(bd, desk);
9762                     }
9763                   break;
9764                }
9765           }
9766      }
9767 #endif
9768 #ifdef _F_ZONE_WINDOW_ROTATION_
9769    if ((e_config->wm_win_rotation) &&
9770        (need_rotation_set))
9771      {
9772         ELB(ELBT_ROT, "NEED ROT", bd->client.win);
9773         _e_border_rotation_check(bd);
9774      }
9775 #endif
9776
9777    /* PRE_POST_FETCH calls e_remember apply for new client */
9778    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
9779    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
9780    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
9781
9782    if (bd->need_reparent)
9783      {
9784         if (!bd->internal)
9785           ecore_x_window_save_set_add(bd->client.win);
9786         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
9787         if (bd->visible)
9788           {
9789              if ((bd->new_client) && (bd->internal) &&
9790                  (bd->internal_ecore_evas))
9791                ecore_evas_show(bd->internal_ecore_evas);
9792              ecore_x_window_show(bd->client.win);
9793           }
9794         bd->need_reparent = 0;
9795      }
9796
9797    if ((bd->client.border.changed) && (!bd->shaded) &&
9798        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
9799      {
9800         const char *bordername;
9801
9802         if (bd->fullscreen)
9803           bordername = "borderless";
9804         else if (bd->bordername)
9805           bordername = bd->bordername;
9806         else if ((bd->client.mwm.borderless) || (bd->borderless))
9807           bordername = "borderless";
9808         else if (((bd->client.icccm.transient_for != 0) ||
9809                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
9810                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
9811                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
9812           bordername = "noresize_dialog";
9813         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
9814                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
9815           bordername = "noresize";
9816         else if (bd->client.shaped)
9817           bordername = "shaped";
9818         else if ((!bd->client.icccm.accepts_focus) &&
9819                  (!bd->client.icccm.take_focus))
9820           bordername = "nofocus";
9821         else if (bd->client.icccm.urgent)
9822           bordername = "urgent";
9823         else if ((bd->client.icccm.transient_for != 0) ||
9824                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
9825           bordername = "dialog";
9826         else if (bd->client.netwm.state.modal)
9827           bordername = "modal";
9828         else if ((bd->client.netwm.state.skip_taskbar) ||
9829                  (bd->client.netwm.state.skip_pager))
9830           bordername = "skipped";
9831         else if ((bd->internal) && (bd->client.icccm.class) &&
9832                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
9833           bordername = "internal_fileman";
9834         else
9835           bordername = e_config->theme_default_border_style;
9836         if (!bordername) bordername = "default";
9837
9838         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
9839           {
9840              Evas_Object *o;
9841              char buf[4096];
9842              int ok;
9843
9844              bd->changes.border = 1;
9845              eina_stringshare_replace(&bd->client.border.name, bordername);
9846
9847              if (bd->bg_object)
9848                {
9849                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
9850                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
9851                   bd->changes.size = 1;
9852                   evas_object_del(bd->bg_object);
9853                }
9854              o = edje_object_add(bd->bg_evas);
9855              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
9856              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
9857              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
9858                {
9859                   if (bd->client.border.name != e_config->theme_default_border_style)
9860                     {
9861                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
9862                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
9863                     }
9864                   if (!ok)
9865                     {
9866                        ok = e_theme_edje_object_set(o, "base/theme/borders",
9867                                                     "e/widgets/border/default/border");
9868                        if (ok)
9869                          {
9870                             /* Reset default border style to default */
9871                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
9872                             e_config_save_queue();
9873                          }
9874                     }
9875                }
9876
9877              bd->shaped = 0;
9878              if (ok)
9879                {
9880                   const char *shape_option, *argb_option;
9881                   int use_argb = 0;
9882
9883                   bd->bg_object = o;
9884
9885                   if ((e_config->use_composite) && (!bd->client.argb))
9886                     {
9887                        argb_option = edje_object_data_get(o, "argb");
9888                        if ((argb_option) && (!strcmp(argb_option, "1")))
9889                          use_argb = 1;
9890
9891                        if (use_argb != bd->argb)
9892                          _e_border_frame_replace(bd, use_argb);
9893
9894                        o = bd->bg_object;
9895                     }
9896
9897                   if (!bd->argb)
9898                     {
9899                        shape_option = edje_object_data_get(o, "shaped");
9900                        if ((shape_option) && (!strcmp(shape_option, "1")))
9901                          bd->shaped = 1;
9902                     }
9903
9904                   if (bd->client.netwm.name)
9905                     edje_object_part_text_set(o, "e.text.title",
9906                                               bd->client.netwm.name);
9907                   else if (bd->client.icccm.title)
9908                     edje_object_part_text_set(o, "e.text.title",
9909                                               bd->client.icccm.title);
9910                }
9911              else
9912                {
9913                   evas_object_del(o);
9914                   bd->bg_object = NULL;
9915                }
9916
9917              _e_border_client_inset_calc(bd);
9918
9919              bd->w += (bd->client_inset.l + bd->client_inset.r);
9920              bd->h += (bd->client_inset.t + bd->client_inset.b);
9921              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
9922              bd->changes.size = 1;
9923              /*  really needed ? */
9924              ecore_x_window_move(bd->client.shell_win,
9925                                  bd->client_inset.l,
9926                                  bd->client_inset.t);
9927
9928              if (bd->maximized != E_MAXIMIZE_NONE)
9929                {
9930                   E_Maximize maximized = bd->maximized;
9931
9932                   /* to force possible resizes */
9933                   bd->maximized = E_MAXIMIZE_NONE;
9934
9935                   _e_border_maximize(bd, maximized);
9936
9937                   /* restore maximized state */
9938                   bd->maximized = maximized;
9939
9940                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
9941                                                bd->maximized & E_MAXIMIZE_VERTICAL);
9942                }
9943              if (bd->bg_object)
9944                {
9945                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
9946                                                   _e_border_cb_signal_bind, bd);
9947                   if (bd->focused)
9948                     {
9949                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
9950                        if (bd->icon_object)
9951                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
9952                     }
9953                   if (bd->shaded)
9954                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
9955                   if (bd->sticky)
9956                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
9957                   if (bd->hung)
9958                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
9959                   // FIXME: in eval -do differently
9960                   //         edje_object_message_signal_process(bd->bg_object);
9961                   //         e_border_frame_recalc(bd);
9962
9963                   evas_object_move(bd->bg_object, 0, 0);
9964                   evas_object_resize(bd->bg_object, bd->w, bd->h);
9965                   evas_object_show(bd->bg_object);
9966                }
9967           }
9968         bd->client.border.changed = 0;
9969
9970         if (bd->icon_object)
9971           {
9972              if (bd->bg_object)
9973                {
9974                   evas_object_show(bd->icon_object);
9975                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
9976                }
9977              else
9978                evas_object_hide(bd->icon_object);
9979           }
9980      }
9981
9982    if (rem_change) e_remember_update(bd);
9983
9984    if (change_urgent)
9985      {
9986         E_Event_Border_Urgent_Change *ev;
9987
9988         if (bd->client.icccm.urgent)
9989           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
9990         else
9991           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
9992
9993         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
9994         ev->border = bd;
9995         e_object_ref(E_OBJECT(bd));
9996         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
9997                         _e_border_event_border_urgent_change_free, NULL);
9998      }
9999
10000    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10001 }
10002
10003 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10004 static void
10005 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10006 {
10007    E_Border* temp_bd = NULL;
10008    E_Border* top_focusable_bd = NULL;
10009    Eina_Bool is_fully_obscured = EINA_FALSE;
10010    Ecore_X_XRegion *visible_region = NULL;
10011    Ecore_X_XRegion *win_region = NULL;
10012    Ecore_X_Rectangle visible_rect, win_rect;
10013    E_Border_List *bl;
10014
10015    // set the entire visible region as a root geometry
10016    visible_rect.x = bd->zone->x;
10017    visible_rect.y = bd->zone->y;
10018    visible_rect.width = bd->zone->w;
10019    visible_rect.height = bd->zone->h;
10020
10021    visible_region = ecore_x_xregion_new();
10022    if (!visible_region) return;
10023
10024    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10025
10026    bl = e_container_border_list_last(bd->zone->container);
10027    while ((temp_bd = e_container_border_list_prev(bl)))
10028      {
10029         if (temp_bd == bd) break;
10030
10031         if (temp_bd == focused) continue;
10032         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10033         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10034         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10035             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10036             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10037             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10038             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10039             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10040             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10041           {
10042              if (!top_focusable_bd)
10043                {
10044                   top_focusable_bd = temp_bd;
10045                }
10046
10047              win_rect.x = temp_bd->x;
10048              win_rect.y = temp_bd->y;
10049              win_rect.width = temp_bd->w;
10050              win_rect.height = temp_bd->h;
10051
10052              // if it stick out or is bigger than the entire visible region,
10053              // clip it by the entire visible's geometry.
10054              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10055                                   win_rect.width, win_rect.height,
10056                                   visible_rect.x, visible_rect.y,
10057                                   (int)(visible_rect.width), (int)(visible_rect.height));
10058
10059              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10060                {
10061                   win_region = ecore_x_xregion_new();
10062                   if (win_region)
10063                     {
10064                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10065                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10066                        ecore_x_xregion_free(win_region);
10067                        win_region = NULL;
10068
10069                        if (ecore_x_xregion_is_empty(visible_region))
10070                          {
10071                             is_fully_obscured = EINA_TRUE;
10072                             break;
10073                          }
10074                     }
10075                }
10076           }
10077      }
10078
10079    if (is_fully_obscured == EINA_TRUE)
10080      {
10081         e_border_focus_set(top_focusable_bd, 1, 1);
10082      }
10083    else
10084      {
10085         e_border_focus_set(bd, 1, 1);
10086      }
10087
10088    if (visible_region) ecore_x_xregion_free(visible_region);
10089    e_container_border_list_free(bl);
10090 }
10091
10092 static void
10093 _e_border_latest_stacked_focus(E_Border *bd)
10094 {
10095    E_Border *temp_bd;
10096    int root_w, root_h;
10097
10098    root_w = bd->zone->w;
10099    root_h = bd->zone->h;
10100
10101    Eina_List *l;
10102    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10103      {
10104         if (bd == temp_bd) continue;
10105         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10106         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10107
10108         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10109             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10110             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10111             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10112             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10113             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10114             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10115           {
10116              _e_border_latest_stacked_focus_check_set(temp_bd);
10117              break;
10118           }
10119      }
10120 }
10121
10122 static void
10123 _e_border_check_stack (E_Border *bd)
10124 {
10125    E_Border* temp_bd = NULL;
10126    E_Border* top_bd = NULL;
10127    int passed_focus = 0;
10128    int passed = 0;
10129    int root_w = bd->zone->w;
10130    int root_h = bd->zone->h;
10131
10132    E_Border_List *bl;
10133    bl = e_container_border_list_last(bd->zone->container);
10134    while ((temp_bd = e_container_border_list_prev(bl)))
10135      {
10136         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10137         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10138         if ((temp_bd != bd) &&
10139             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10140
10141         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10142            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10143            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10144            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10145            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10146            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10147            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10148           {
10149              if (bd == temp_bd)
10150                {
10151                   if (!passed)
10152                     {
10153                        e_border_focus_set_with_pointer(bd);
10154                        break;
10155                     }
10156                   else
10157                     {
10158                        if (!passed_focus)
10159                          {
10160                             e_border_focus_set_with_pointer(top_bd);
10161                          }
10162                        break;
10163                     }
10164                }
10165              else
10166                {
10167                   if (!passed)
10168                     {
10169                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10170                          {
10171                             if (!bd->lock_focus_out)
10172                               {
10173                                  e_border_focus_latest_set(bd);
10174                               }
10175                          }
10176                     }
10177                }
10178
10179              if (!passed)
10180                {
10181                   passed = 1;
10182                   top_bd = temp_bd;
10183                }
10184
10185              if (temp_bd == focused)
10186                {
10187                   passed_focus = 1;
10188                }
10189           }
10190      }
10191    e_container_border_list_free(bl);
10192 }
10193
10194 static void
10195 _e_border_focus_top_stack_set(E_Border* bd)
10196 {
10197    E_Border *temp_bd;
10198    int root_w, root_h;
10199
10200    root_w = bd->zone->w;
10201    root_h = bd->zone->h;
10202
10203    E_Border_List *bl;
10204    bl = e_container_border_list_last(bd->zone->container);
10205    while ((temp_bd = e_container_border_list_prev(bl)))
10206      {
10207         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10208         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10209         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
10210
10211         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10212            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10213            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10214            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10215            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10216            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10217            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10218           {
10219              if (!temp_bd->focused)
10220                {
10221                   /* this border is the top of the latest stack */
10222                   e_border_focus_set (temp_bd, 1, 1);
10223                }
10224              break;
10225           }
10226      }
10227    e_container_border_list_free(bl);
10228 }
10229 #endif
10230
10231 static void
10232 _e_border_eval(E_Border *bd)
10233 {
10234    E_Event_Border_Property *event;
10235    E_Border_Pending_Move_Resize *pnd;
10236    int rem_change = 0;
10237    int send_event = 1;
10238
10239    if (e_object_is_del(E_OBJECT(bd)))
10240      {
10241         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
10242         bd->changed = 0;
10243         return;
10244      }
10245
10246    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
10247
10248    if (bd->new_client)
10249      {
10250         int zx = 0, zy = 0, zw = 0, zh = 0;
10251
10252         if (bd->zone)
10253           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
10254
10255         /*
10256          * Limit maximum size of windows to useful geometry
10257          */
10258         // TODO: temoporary limited maximize algorithm
10259         // ->
10260         /*if (bd->w > zw)
10261           rw = zw;
10262           else
10263           rw = bd->w;
10264
10265           if (bd->h > zh)
10266           rh = zh;
10267           else
10268           rh = bd->h;
10269
10270           if ((rw != bd->w) || (rh != bd->h))
10271           {
10272           bd->w = rw;
10273           bd->h = rh;
10274           e_border_resize (bd, bd->w, bd->h);
10275           }*/
10276         // <-
10277
10278         if (bd->re_manage)
10279           {
10280              bd->x -= bd->client_inset.l;
10281              bd->y -= bd->client_inset.t;
10282              bd->changes.pos = 1;
10283              bd->placed = 1;
10284           }
10285         else if ((!bd->placed) && (bd->client.icccm.request_pos))
10286           {
10287
10288              Ecore_X_Window_Attributes *att;
10289              int bw;
10290
10291              att = &bd->client.initial_attributes;
10292              bw = att->border * 2;
10293              switch (bd->client.icccm.gravity)
10294                {
10295                 case ECORE_X_GRAVITY_N:
10296                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10297                    bd->y = att->y;
10298                    break;
10299
10300                 case ECORE_X_GRAVITY_NE:
10301                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10302                    bd->y = att->y;
10303                    break;
10304
10305                 case ECORE_X_GRAVITY_E:
10306                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10307                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10308                    break;
10309
10310                 case ECORE_X_GRAVITY_SE:
10311                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10312                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10313                    break;
10314
10315                 case ECORE_X_GRAVITY_S:
10316                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10317                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10318                    break;
10319
10320                 case ECORE_X_GRAVITY_SW:
10321                    bd->x = att->x;
10322                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10323                    break;
10324
10325                 case ECORE_X_GRAVITY_W:
10326                    bd->x = att->x;
10327                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10328                    break;
10329
10330                 case ECORE_X_GRAVITY_CENTER:
10331                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10332                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10333                    break;
10334
10335                 case ECORE_X_GRAVITY_NW:
10336                 default:
10337                    bd->x = att->x;
10338                    bd->y = att->y;
10339                }
10340
10341              /*
10342               * This ensures that windows that like to open with a x/y
10343               * position smaller than returned by e_zone_useful_geometry_get()
10344               * are moved to useful positions.
10345               */
10346              // ->
10347              if (e_config->geometry_auto_move)
10348                {
10349                   if (bd->x < zx)
10350                     bd->x = zx;
10351
10352                   if (bd->y < zy)
10353                     bd->y = zy;
10354
10355                   if (bd->x + bd->w > zx + zw)
10356                     bd->x = zx + zw - bd->w;
10357
10358                   if (bd->y + bd->h > zy + zh)
10359                     bd->y = zy + zh - bd->h;
10360                   // <--
10361
10362                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
10363                     {
10364                        bd->changes.pos = 1;
10365                        bd->placed = 1;
10366                     }
10367                }
10368              else
10369                {
10370                   bd->changes.pos = 1;
10371                   bd->placed = 1;
10372                }
10373           }
10374         if (!bd->placed)
10375           {
10376              /* FIXME: special placement for dialogs etc. etc. etc goes
10377               * here */
10378              /* FIXME: what if parent is not on this desktop - or zone? */
10379              if ((bd->parent) && (bd->parent->visible))
10380                {
10381                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
10382                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
10383                   bd->changes.pos = 1;
10384                   bd->placed = 1;
10385                }
10386 #if 0
10387              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10388                {
10389                   /* TODO: Place in center of group */
10390                }
10391 #endif
10392              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
10393                {
10394                   bd->x = zx + ((zw - bd->w) / 2);
10395                   bd->y = zy + ((zh - bd->h) / 2);
10396                   bd->changes.pos = 1;
10397                   bd->placed = 1;
10398                }
10399           }
10400         if (!bd->placed)
10401           {
10402              Eina_List *skiplist = NULL;
10403              int new_x, new_y;
10404
10405              if (zw > bd->w)
10406                new_x = zx + (rand() % (zw - bd->w));
10407              else
10408                new_x = zx;
10409              if (zh > bd->h)
10410                new_y = zy + (rand() % (zh - bd->h));
10411              else
10412                new_y = zy;
10413
10414              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
10415                {
10416                   skiplist = eina_list_append(skiplist, bd);
10417                   if (bd->desk)
10418                     e_place_desk_region_smart(bd->desk, skiplist,
10419                                               bd->x, bd->y, bd->w, bd->h,
10420                                               &new_x, &new_y);
10421                   else
10422                     e_place_zone_region_smart(bd->zone, skiplist,
10423                                               bd->x, bd->y, bd->w, bd->h,
10424                                               &new_x, &new_y);
10425                   eina_list_free(skiplist);
10426                }
10427              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
10428                {
10429                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
10430                                       &new_x, &new_y);
10431                }
10432              else
10433                {
10434                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
10435                                       bd->client_inset.t, &new_x, &new_y);
10436                }
10437              bd->x = new_x;
10438              bd->y = new_y;
10439              bd->changes.pos = 1;
10440           }
10441
10442         EINA_LIST_FREE(bd->pending_move_resize, pnd)
10443           {
10444              if ((!bd->lock_client_location) && (pnd->move))
10445                {
10446                   bd->x = pnd->x;
10447                   bd->y = pnd->y;
10448                   bd->changes.pos = 1;
10449                   bd->placed = 1;
10450                   if (pnd->without_border)
10451                     {
10452                        bd->x -= bd->client_inset.l;
10453                        bd->y -= bd->client_inset.t;
10454                     }
10455                }
10456              if ((!bd->lock_client_size) && (pnd->resize))
10457                {
10458                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
10459                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
10460                   bd->client.w = pnd->w;
10461                   bd->client.h = pnd->h;
10462                   bd->changes.size = 1;
10463                }
10464
10465              free(pnd);
10466           }
10467
10468         /* Recreate state */
10469         e_hints_window_init(bd);
10470         if ((bd->client.e.state.centered) &&
10471             ((!bd->remember) ||
10472              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
10473           {
10474              bd->x = zx + (zw - bd->w) / 2;
10475              bd->y = zy + (zh - bd->h) / 2;
10476              bd->changes.pos = 1;
10477              bd->placed = 1;
10478           }
10479
10480         _e_border_client_move_resize_send(bd);
10481
10482         /* if the explicit geometry request asks for the app to be
10483          * in another zone - well move it there */
10484         {
10485            E_Zone *zone;
10486
10487            zone = e_container_zone_at_point_get(bd->zone->container,
10488                                                 bd->x + (bd->w / 2),
10489                                                 bd->y + (bd->h / 2));
10490            if (!zone)
10491              zone = e_container_zone_at_point_get(bd->zone->container,
10492                                                   bd->x,
10493                                                   bd->y);
10494            if (!zone)
10495              zone = e_container_zone_at_point_get(bd->zone->container,
10496                                                   bd->x + bd->w - 1,
10497                                                   bd->y);
10498            if (!zone)
10499              zone = e_container_zone_at_point_get(bd->zone->container,
10500                                                   bd->x + bd->w - 1,
10501                                                   bd->y + bd->h - 1);
10502            if (!zone)
10503              zone = e_container_zone_at_point_get(bd->zone->container,
10504                                                   bd->x,
10505                                                   bd->y + bd->h - 1);
10506            if ((zone) && (zone != bd->zone))
10507              e_border_zone_set(bd, zone);
10508         }
10509      }
10510
10511    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
10512
10513    /* effect changes to the window border itself */
10514    if ((bd->changes.shading))
10515      {
10516         /*  show at start of unshade (but don't hide until end of shade) */
10517         if (bd->shaded)
10518           ecore_x_window_raise(bd->client.shell_win);
10519         bd->changes.shading = 0;
10520         rem_change = 1;
10521      }
10522    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
10523      {
10524         if (bd->shaded)
10525           ecore_x_window_lower(bd->client.shell_win);
10526         else
10527           ecore_x_window_raise(bd->client.shell_win);
10528         bd->changes.shaded = 0;
10529         rem_change = 1;
10530      }
10531    else if ((bd->changes.shaded) && (bd->changes.pos))
10532      {
10533         if (bd->shaded)
10534           ecore_x_window_lower(bd->client.shell_win);
10535         else
10536           ecore_x_window_raise(bd->client.shell_win);
10537         bd->changes.size = 1;
10538         bd->changes.shaded = 0;
10539         rem_change = 1;
10540      }
10541    else if ((bd->changes.shaded) && (bd->changes.size))
10542      {
10543         if (bd->shaded)
10544           ecore_x_window_lower(bd->client.shell_win);
10545         else
10546           ecore_x_window_raise(bd->client.shell_win);
10547         bd->changes.shaded = 0;
10548         rem_change = 1;
10549      }
10550    else if (bd->changes.shaded)
10551      {
10552         if (bd->shaded)
10553           ecore_x_window_lower(bd->client.shell_win);
10554         else
10555           ecore_x_window_raise(bd->client.shell_win);
10556         bd->changes.size = 1;
10557         bd->changes.shaded = 0;
10558         rem_change = 1;
10559      }
10560
10561    if (bd->changes.size)
10562      {
10563         int x = 0, y = 0, xx = 0, yy = 0;
10564
10565         if ((bd->shaded) && (!bd->shading))
10566           {
10567              evas_obscured_clear(bd->bg_evas);
10568           }
10569         else
10570           {
10571              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
10572              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
10573
10574              evas_obscured_clear(bd->bg_evas);
10575              evas_obscured_rectangle_add(bd->bg_evas,
10576                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
10577
10578              if (bd->shading)
10579                {
10580                   if (bd->shade.dir == E_DIRECTION_UP)
10581                     {
10582                        y = yy - bd->client.h;
10583                     }
10584                   else if (bd->shade.dir == E_DIRECTION_LEFT)
10585                     {
10586                        x = xx - bd->client.w;
10587                     }
10588                }
10589           }
10590
10591         if (bd->client.e.state.video)
10592           {
10593              if (bd->client.e.state.video_position.updated)
10594                {
10595                   ecore_x_window_move(bd->win,
10596                                       bd->client.e.state.video_parent_border->x +
10597                                       bd->client.e.state.video_parent_border->client_inset.l +
10598                                       bd->client.e.state.video_parent_border->fx.x +
10599                                       bd->client.e.state.video_position.x,
10600                                       bd->client.e.state.video_parent_border->y +
10601                                       bd->client.e.state.video_parent_border->client_inset.t +
10602                                       bd->client.e.state.video_parent_border->fx.y +
10603                                       bd->client.e.state.video_position.y);
10604                   bd->client.e.state.video_position.updated = 0;
10605                }
10606           }
10607         else if (!bd->changes.pos)
10608           {
10609              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
10610              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
10611              bd->post_resize = 1;
10612           }
10613         else
10614           {
10615              E_Border *tmp;
10616              Eina_List *l;
10617
10618              ecore_x_window_move_resize(bd->win,
10619                                         bd->x + bd->fx.x,
10620                                         bd->y + bd->fx.y,
10621                                         bd->w, bd->h);
10622
10623              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
10624                ecore_x_window_move(tmp->win,
10625                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
10626                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
10627           }
10628
10629         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
10630
10631         if ((!bd->shaded) || (bd->shading))
10632           ecore_x_window_move_resize(bd->client.shell_win,
10633                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
10634
10635         if (bd->internal_ecore_evas)
10636           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
10637         else if (!bd->client.e.state.video)
10638           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
10639
10640         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
10641         evas_object_resize(bd->bg_object, bd->w, bd->h);
10642         e_container_shape_resize(bd->shape, bd->w, bd->h);
10643         if (bd->changes.pos)
10644           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
10645
10646         _e_border_client_move_resize_send(bd);
10647
10648         bd->changes.pos = 0;
10649         bd->changes.size = 0;
10650         rem_change = 1;
10651      }
10652    else if (bd->changes.pos)
10653      {
10654         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
10655         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
10656         bd->post_move = 1;
10657
10658         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
10659
10660         _e_border_client_move_resize_send(bd);
10661
10662         bd->changes.pos = 0;
10663         rem_change = 1;
10664      }
10665
10666    if (bd->changes.reset_gravity)
10667      {
10668         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
10669         bd->changes.reset_gravity = 0;
10670         rem_change = 1;
10671      }
10672
10673    if (bd->need_shape_merge)
10674      {
10675         _e_border_shape_input_rectangle_set(bd);
10676         if ((bd->shaped) || (bd->client.shaped))
10677           {
10678              Ecore_X_Window twin, twin2;
10679              int x, y;
10680
10681              twin = ecore_x_window_override_new
10682                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
10683              if (bd->shaped)
10684                ecore_x_window_shape_window_set(twin, bd->bg_win);
10685              else
10686                {
10687                   Ecore_X_Rectangle rects[4];
10688
10689                   rects[0].x = 0;
10690                   rects[0].y = 0;
10691                   rects[0].width = bd->w;
10692                   rects[0].height = bd->client_inset.t;
10693                   rects[1].x = 0;
10694                   rects[1].y = bd->client_inset.t;
10695                   rects[1].width = bd->client_inset.l;
10696                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
10697                   rects[2].x = bd->w - bd->client_inset.r;
10698                   rects[2].y = bd->client_inset.t;
10699                   rects[2].width = bd->client_inset.r;
10700                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
10701                   rects[3].x = 0;
10702                   rects[3].y = bd->h - bd->client_inset.b;
10703                   rects[3].width = bd->w;
10704                   rects[3].height = bd->client_inset.b;
10705                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
10706                }
10707              twin2 = ecore_x_window_override_new
10708                (bd->zone->container->scratch_win, 0, 0,
10709                 bd->w - bd->client_inset.l - bd->client_inset.r,
10710                 bd->h - bd->client_inset.t - bd->client_inset.b);
10711              x = 0;
10712              y = 0;
10713              if ((bd->shading) || (bd->shaded))
10714                {
10715                   if (bd->shade.dir == E_DIRECTION_UP)
10716                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
10717                   else if (bd->shade.dir == E_DIRECTION_LEFT)
10718                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
10719                }
10720              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
10721                                                 x, y);
10722              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
10723                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
10724                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
10725              ecore_x_window_shape_window_add_xy(twin, twin2,
10726                                                 bd->client_inset.l,
10727                                                 bd->client_inset.t);
10728              ecore_x_window_free(twin2);
10729              ecore_x_window_shape_window_set(bd->win, twin);
10730              ecore_x_window_free(twin);
10731           }
10732         else
10733           ecore_x_window_shape_mask_set(bd->win, 0);
10734         //      bd->need_shape_export = 1;
10735         bd->need_shape_merge = 0;
10736      }
10737
10738    if (bd->need_shape_export)
10739      {
10740         Ecore_X_Rectangle *rects, *orects;
10741         int num;
10742
10743         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
10744         if (rects)
10745           {
10746              int changed;
10747
10748              changed = 1;
10749              if ((num == bd->shape_rects_num) && (bd->shape_rects))
10750                {
10751                   int i;
10752
10753                   orects = bd->shape_rects;
10754                   changed = 0;
10755                   for (i = 0; i < num; i++)
10756                     {
10757                        if (rects[i].x < 0)
10758                          {
10759                             rects[i].width -= rects[i].x;
10760                             rects[i].x = 0;
10761                          }
10762                        if ((rects[i].x + (int)rects[i].width) > bd->w)
10763                          rects[i].width = rects[i].width - rects[i].x;
10764                        if (rects[i].y < 0)
10765                          {
10766                             rects[i].height -= rects[i].y;
10767                             rects[i].y = 0;
10768                          }
10769                        if ((rects[i].y + (int)rects[i].height) > bd->h)
10770                          rects[i].height = rects[i].height - rects[i].y;
10771
10772                        if ((orects[i].x != rects[i].x) ||
10773                            (orects[i].y != rects[i].y) ||
10774                            (orects[i].width != rects[i].width) ||
10775                            (orects[i].height != rects[i].height))
10776                          {
10777                             changed = 1;
10778                             break;
10779                          }
10780                     }
10781                }
10782              if (changed)
10783                {
10784                   if (bd->client.shaped)
10785                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
10786                   else
10787                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
10788                   E_FREE(bd->shape_rects);
10789                   bd->shape_rects = rects;
10790                   bd->shape_rects_num = num;
10791                   e_container_shape_rects_set(bd->shape, rects, num);
10792                }
10793              else
10794                free(rects);
10795           }
10796         else
10797           {
10798              E_FREE(bd->shape_rects);
10799              bd->shape_rects = NULL;
10800              bd->shape_rects_num = 0;
10801              e_container_shape_rects_set(bd->shape, NULL, 0);
10802           }
10803         bd->need_shape_export = 0;
10804      }
10805
10806    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
10807      {
10808         int x, y;
10809
10810         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
10811         if ((!bd->placed) && (!bd->re_manage) &&
10812             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
10813             (!((bd->client.icccm.transient_for != 0) ||
10814                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
10815             (!bdmove) && (!bdresize))
10816           {
10817              /* Set this window into moving state */
10818
10819              bd->cur_mouse_action = e_action_find("window_move");
10820              if (bd->cur_mouse_action)
10821                {
10822                   if ((!bd->cur_mouse_action->func.end_mouse) &&
10823                       (!bd->cur_mouse_action->func.end))
10824                     bd->cur_mouse_action = NULL;
10825                   if (bd->cur_mouse_action)
10826                     {
10827                        bd->x = x - (bd->w >> 1);
10828                        bd->y = y - (bd->client_inset.t >> 1);
10829                        bd->changed = 1;
10830                        bd->changes.pos = 1;
10831
10832                        _e_border_client_move_resize_send(bd);
10833                     }
10834                }
10835           }
10836
10837         _e_border_show(bd);
10838
10839         if (bd->cur_mouse_action)
10840           {
10841              bd->moveinfo.down.x = bd->x + bd->fx.x;
10842              bd->moveinfo.down.y = bd->y + bd->fx.y;
10843              bd->moveinfo.down.w = bd->w;
10844              bd->moveinfo.down.h = bd->h;
10845              bd->mouse.current.mx = x;
10846              bd->mouse.current.my = y;
10847              bd->moveinfo.down.button = 0;
10848              bd->moveinfo.down.mx = x;
10849              bd->moveinfo.down.my = y;
10850
10851              grabbed = 1;
10852              e_object_ref(E_OBJECT(bd->cur_mouse_action));
10853              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
10854              if (e_config->border_raise_on_mouse_action)
10855                e_border_raise(bd);
10856              e_border_focus_set(bd, 1, 1);
10857           }
10858         bd->changes.visible = 0;
10859         rem_change = 1;
10860      }
10861
10862    if (bd->changes.icon)
10863      {
10864         if (bd->desktop)
10865           {
10866              efreet_desktop_free(bd->desktop);
10867              bd->desktop = NULL;
10868           }
10869         if (bd->icon_object)
10870           {
10871              evas_object_del(bd->icon_object);
10872              bd->icon_object = NULL;
10873           }
10874         if (bd->remember && bd->remember->prop.desktop_file)
10875           {
10876              const char *desktop = bd->remember->prop.desktop_file;
10877
10878              bd->desktop = efreet_desktop_get(desktop);
10879              if (!bd->desktop)
10880                bd->desktop = efreet_util_desktop_name_find(desktop);
10881           }
10882         if (!bd->desktop)
10883           {
10884              if ((bd->client.icccm.name) && (bd->client.icccm.class))
10885                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
10886                                                                bd->client.icccm.class);
10887           }
10888         if (!bd->desktop)
10889           {
10890              /* libreoffice and maybe others match window class
10891                 with .desktop file name */
10892              if (bd->client.icccm.class)
10893                {
10894                   char buf[128];
10895                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
10896                   bd->desktop = efreet_util_desktop_file_id_find(buf);
10897                }
10898           }
10899         if (!bd->desktop)
10900           {
10901              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
10902                                                       bd->client.netwm.pid);
10903              if (bd->desktop) efreet_desktop_ref(bd->desktop);
10904           }
10905         if (!bd->desktop && bd->client.icccm.name)
10906           {
10907              /* this works for most cases as fallback. useful when app is
10908                 run from a shell  */
10909              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
10910           }
10911         if (!bd->desktop && bd->client.icccm.transient_for)
10912           {
10913              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
10914              if (bd2 && bd2->desktop)
10915                {
10916                   efreet_desktop_ref(bd2->desktop);
10917                   bd->desktop = bd2->desktop;
10918                }
10919           }
10920         if (bd->desktop)
10921           {
10922              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
10923                                             bd->desktop->orig_path);
10924           }
10925
10926         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
10927         if ((bd->focused) && (bd->icon_object))
10928           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10929         if (bd->bg_object)
10930           {
10931              evas_object_show(bd->icon_object);
10932              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10933           }
10934         else
10935           evas_object_hide(bd->icon_object);
10936
10937         {
10938            E_Event_Border_Icon_Change *ev;
10939
10940            ev = E_NEW(E_Event_Border_Icon_Change, 1);
10941            ev->border = bd;
10942            e_object_ref(E_OBJECT(bd));
10943            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
10944            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
10945                            _e_border_event_border_icon_change_free, NULL);
10946         }
10947         bd->changes.icon = 0;
10948      }
10949
10950    bd->new_client = 0;
10951    bd->changed = 0;
10952    bd->changes.stack = 0;
10953    bd->changes.prop = 0;
10954
10955    if ((bd->take_focus) || (bd->want_focus))
10956      {
10957         bd->take_focus = 0;
10958 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10959         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
10960             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
10961             (bd->want_focus))
10962 #else // original
10963         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
10964 #endif
10965           {
10966              bd->want_focus = 0;
10967 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10968              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
10969                 _e_border_check_stack(bd);
10970              else
10971 #endif
10972              e_border_focus_set_with_pointer(bd);
10973           }
10974         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
10975           {
10976              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
10977                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
10978                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
10979                    e_border_focused_get())))
10980                {
10981                   e_border_focus_set_with_pointer(bd);
10982                }
10983           }
10984         else
10985           {
10986              /* focus window by default when it is the only one on desk */
10987              E_Border *bd2 = NULL;
10988              Eina_List *l;
10989              EINA_LIST_FOREACH(focus_stack, l, bd2)
10990                {
10991                   if (bd == bd2) continue;
10992                   if ((!bd2->iconic) && (bd2->visible) &&
10993                       ((bd->desk == bd2->desk) || bd2->sticky))
10994                     break;
10995                }
10996
10997              if (!bd2)
10998                {
10999                   e_border_focus_set_with_pointer(bd);
11000                }
11001           }
11002      }
11003
11004    if (bd->need_maximize)
11005      {
11006         E_Maximize max;
11007         max = bd->maximized;
11008         bd->maximized = E_MAXIMIZE_NONE;
11009         e_border_maximize(bd, max);
11010         bd->need_maximize = 0;
11011      }
11012
11013    if (bd->need_fullscreen)
11014      {
11015         e_border_fullscreen(bd, e_config->fullscreen_policy);
11016         bd->need_fullscreen = 0;
11017      }
11018
11019    if (rem_change)
11020      e_remember_update(bd);
11021
11022    if (send_event) // FIXME: send only if a property changed - above need to
11023      { // check on that. for now - always send.
11024         event = E_NEW(E_Event_Border_Property, 1);
11025         event->border = bd;
11026         e_object_ref(E_OBJECT(bd));
11027         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11028      }
11029    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11030 }
11031
11032 static void
11033 _e_border_moveinfo_gather(E_Border   *bd,
11034                           const char *source)
11035 {
11036    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11037    else if (e_util_glob_match(source, "mouse,*,2"))
11038      bd->moveinfo.down.button = 2;
11039    else if (e_util_glob_match(source, "mouse,*,3"))
11040      bd->moveinfo.down.button = 3;
11041    else bd->moveinfo.down.button = 0;
11042    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11043      {
11044         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11045         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11046      }
11047    else
11048      {
11049         bd->moveinfo.down.mx = bd->mouse.current.mx;
11050         bd->moveinfo.down.my = bd->mouse.current.my;
11051      }
11052 }
11053
11054 static void
11055 _e_border_resize_handle(E_Border *bd)
11056 {
11057    int x, y, w, h;
11058    int new_x, new_y, new_w, new_h;
11059    int tw, th;
11060    Eina_List *skiplist = NULL;
11061
11062    x = bd->x;
11063    y = bd->y;
11064    w = bd->w;
11065    h = bd->h;
11066
11067    if ((bd->resize_mode == RESIZE_TR) ||
11068        (bd->resize_mode == RESIZE_R) ||
11069        (bd->resize_mode == RESIZE_BR))
11070      {
11071         if ((bd->moveinfo.down.button >= 1) &&
11072             (bd->moveinfo.down.button <= 3))
11073           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11074             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11075         else
11076           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11077      }
11078    else if ((bd->resize_mode == RESIZE_TL) ||
11079             (bd->resize_mode == RESIZE_L) ||
11080             (bd->resize_mode == RESIZE_BL))
11081      {
11082         if ((bd->moveinfo.down.button >= 1) &&
11083             (bd->moveinfo.down.button <= 3))
11084           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11085             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11086         else
11087           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11088      }
11089
11090    if ((bd->resize_mode == RESIZE_TL) ||
11091        (bd->resize_mode == RESIZE_T) ||
11092        (bd->resize_mode == RESIZE_TR))
11093      {
11094         if ((bd->moveinfo.down.button >= 1) &&
11095             (bd->moveinfo.down.button <= 3))
11096           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11097             (bd->mouse.current.my - bd->moveinfo.down.my);
11098         else
11099           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11100      }
11101    else if ((bd->resize_mode == RESIZE_BL) ||
11102             (bd->resize_mode == RESIZE_B) ||
11103             (bd->resize_mode == RESIZE_BR))
11104      {
11105         if ((bd->moveinfo.down.button >= 1) &&
11106             (bd->moveinfo.down.button <= 3))
11107           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11108             (bd->mouse.current.my - bd->moveinfo.down.my);
11109         else
11110           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11111      }
11112
11113    tw = bd->w;
11114    th = bd->h;
11115
11116    if ((bd->resize_mode == RESIZE_TL) ||
11117        (bd->resize_mode == RESIZE_L) ||
11118        (bd->resize_mode == RESIZE_BL))
11119      x += (tw - w);
11120    if ((bd->resize_mode == RESIZE_TL) ||
11121        (bd->resize_mode == RESIZE_T) ||
11122        (bd->resize_mode == RESIZE_TR))
11123      y += (th - h);
11124
11125    skiplist = eina_list_append(skiplist, bd);
11126    e_resist_container_border_position(bd->zone->container, skiplist,
11127                                       bd->x, bd->y, bd->w, bd->h,
11128                                       x, y, w, h,
11129                                       &new_x, &new_y, &new_w, &new_h);
11130    eina_list_free(skiplist);
11131
11132    w = new_w;
11133    h = new_h;
11134    e_border_resize_limit(bd, &new_w, &new_h);
11135    if ((bd->resize_mode == RESIZE_TL) ||
11136        (bd->resize_mode == RESIZE_L) ||
11137        (bd->resize_mode == RESIZE_BL))
11138      new_x += (w - new_w);
11139    if ((bd->resize_mode == RESIZE_TL) ||
11140        (bd->resize_mode == RESIZE_T) ||
11141        (bd->resize_mode == RESIZE_TR))
11142      new_y += (h - new_h);
11143
11144    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11145 }
11146
11147 static Eina_Bool
11148 _e_border_shade_animator(void *data)
11149 {
11150    E_Border *bd = data;
11151    double dt, val;
11152    double dur = bd->client.h / e_config->border_shade_speed;
11153
11154    dt = ecore_loop_time_get() - bd->shade.start;
11155    val = dt / dur;
11156
11157    if (val < 0.0) val = 0.0;
11158    else if (val > 1.0) val = 1.0;
11159
11160    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11161      {
11162         bd->shade.val =
11163            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 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_DECELERATE)
11167      {
11168         bd->shade.val =
11169            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 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_ACCELERATE)
11173      {
11174         bd->shade.val =
11175            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 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_LINEAR)
11179      {
11180         bd->shade.val =
11181            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 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_ACCELERATE_LOTS)
11185      {
11186         bd->shade.val =
11187            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_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_DECELERATE_LOTS)
11191      {
11192         bd->shade.val =
11193            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_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_SINUSOIDAL_LOTS)
11197      {
11198         bd->shade.val =
11199            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.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)
11203      {
11204         bd->shade.val =
11205            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
11206         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11207      }
11208    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
11209      {
11210         bd->shade.val =
11211            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
11212         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11213      }
11214    else
11215      {
11216         bd->shade.val =
11217            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11218         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11219      }
11220
11221    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
11222    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
11223    else if (bd->shade.val > .999)
11224      bd->shade.val = 1.0;
11225
11226    if (bd->shade.dir == E_DIRECTION_UP)
11227      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11228    else if (bd->shade.dir == E_DIRECTION_DOWN)
11229      {
11230         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11231         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
11232         bd->changes.pos = 1;
11233      }
11234    else if (bd->shade.dir == E_DIRECTION_LEFT)
11235      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11236    else if (bd->shade.dir == E_DIRECTION_RIGHT)
11237      {
11238         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11239         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
11240         bd->changes.pos = 1;
11241      }
11242
11243    if ((bd->shaped) || (bd->client.shaped))
11244      {
11245         bd->need_shape_merge = 1;
11246         bd->need_shape_export = 1;
11247      }
11248    if (bd->shaped_input)
11249      {
11250         bd->need_shape_merge = 1;
11251      }
11252    bd->changes.size = 1;
11253    bd->changed = 1;
11254
11255    /* we're done */
11256    if (val == 1)
11257      {
11258         E_Event_Border_Resize *ev;
11259
11260         bd->shading = 0;
11261         bd->shaded = !(bd->shaded);
11262         bd->changes.size = 1;
11263         bd->changes.shaded = 1;
11264         bd->changes.shading = 1;
11265         bd->changed = 1;
11266         bd->shade.anim = NULL;
11267
11268         if (bd->shaded)
11269           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
11270         else
11271           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
11272         edje_object_message_signal_process(bd->bg_object);
11273         e_border_frame_recalc(bd);
11274
11275         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
11276         ev = E_NEW(E_Event_Border_Resize, 1);
11277         ev->border = bd;
11278         e_object_ref(E_OBJECT(bd));
11279 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
11280         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
11281         return ECORE_CALLBACK_CANCEL;
11282      }
11283    return ECORE_CALLBACK_RENEW;
11284 }
11285
11286 static void
11287 _e_border_event_border_resize_free(void *data __UNUSED__,
11288                                    void      *ev)
11289 {
11290    E_Event_Border_Resize *e;
11291
11292    e = ev;
11293 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
11294    e_object_unref(E_OBJECT(e->border));
11295    E_FREE(e);
11296 }
11297
11298 static void
11299 _e_border_event_border_move_free(void *data __UNUSED__,
11300                                  void      *ev)
11301 {
11302    E_Event_Border_Move *e;
11303
11304    e = ev;
11305 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
11306    e_object_unref(E_OBJECT(e->border));
11307    E_FREE(e);
11308 }
11309
11310 static void
11311 _e_border_event_border_add_free(void *data __UNUSED__,
11312                                 void      *ev)
11313 {
11314    E_Event_Border_Add *e;
11315
11316    e = ev;
11317 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
11318    e_object_unref(E_OBJECT(e->border));
11319    E_FREE(e);
11320 }
11321
11322 static void
11323 _e_border_event_border_remove_free(void *data __UNUSED__,
11324                                    void      *ev)
11325 {
11326    E_Event_Border_Remove *e;
11327
11328    e = ev;
11329 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
11330    e_object_unref(E_OBJECT(e->border));
11331    E_FREE(e);
11332 }
11333
11334 static void
11335 _e_border_event_border_show_free(void *data __UNUSED__,
11336                                  void      *ev)
11337 {
11338    E_Event_Border_Show *e;
11339
11340    e = ev;
11341 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
11342    e_object_unref(E_OBJECT(e->border));
11343    E_FREE(e);
11344 }
11345
11346 static void
11347 _e_border_event_border_hide_free(void *data __UNUSED__,
11348                                  void      *ev)
11349 {
11350    E_Event_Border_Hide *e;
11351
11352    e = ev;
11353 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
11354    e_object_unref(E_OBJECT(e->border));
11355    E_FREE(e);
11356 }
11357
11358 static void
11359 _e_border_event_border_iconify_free(void *data __UNUSED__,
11360                                     void      *ev)
11361 {
11362    E_Event_Border_Iconify *e;
11363
11364    e = ev;
11365 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
11366    e_object_unref(E_OBJECT(e->border));
11367    E_FREE(e);
11368 }
11369
11370 static void
11371 _e_border_event_border_uniconify_free(void *data __UNUSED__,
11372                                       void      *ev)
11373 {
11374    E_Event_Border_Uniconify *e;
11375
11376    e = ev;
11377 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
11378    e_object_unref(E_OBJECT(e->border));
11379    E_FREE(e);
11380 }
11381
11382 static void
11383 _e_border_event_border_stick_free(void *data __UNUSED__,
11384                                   void      *ev)
11385 {
11386    E_Event_Border_Stick *e;
11387
11388    e = ev;
11389 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
11390    e_object_unref(E_OBJECT(e->border));
11391    E_FREE(e);
11392 }
11393
11394 static void
11395 _e_border_event_border_unstick_free(void *data __UNUSED__,
11396                                     void      *ev)
11397 {
11398    E_Event_Border_Unstick *e;
11399
11400    e = ev;
11401 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
11402    e_object_unref(E_OBJECT(e->border));
11403    E_FREE(e);
11404 }
11405
11406 static void
11407 _e_border_event_border_zone_set_free(void *data __UNUSED__,
11408                                      void      *ev)
11409 {
11410    E_Event_Border_Zone_Set *e;
11411
11412    e = ev;
11413 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
11414    e_object_unref(E_OBJECT(e->border));
11415    e_object_unref(E_OBJECT(e->zone));
11416    E_FREE(e);
11417 }
11418
11419 static void
11420 _e_border_event_border_desk_set_free(void *data __UNUSED__,
11421                                      void      *ev)
11422 {
11423    E_Event_Border_Desk_Set *e;
11424
11425    e = ev;
11426 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
11427    e_object_unref(E_OBJECT(e->border));
11428    e_object_unref(E_OBJECT(e->desk));
11429    E_FREE(e);
11430 }
11431
11432 static void
11433 _e_border_event_border_stack_free(void *data __UNUSED__,
11434                                   void      *ev)
11435 {
11436    E_Event_Border_Stack *e;
11437
11438    e = ev;
11439 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
11440    e_object_unref(E_OBJECT(e->border));
11441    if (e->stack)
11442      {
11443 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
11444           e_object_unref(E_OBJECT(e->stack));
11445      }
11446    E_FREE(e);
11447 }
11448
11449 static void
11450 _e_border_event_border_icon_change_free(void *data __UNUSED__,
11451                                         void      *ev)
11452 {
11453    E_Event_Border_Icon_Change *e;
11454
11455    e = ev;
11456 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
11457    e_object_unref(E_OBJECT(e->border));
11458    E_FREE(e);
11459 }
11460
11461 static void
11462 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
11463                                           void      *ev)
11464 {
11465    E_Event_Border_Urgent_Change *e;
11466
11467    e = ev;
11468    e_object_unref(E_OBJECT(e->border));
11469    E_FREE(e);
11470 }
11471
11472 static void
11473 _e_border_event_border_focus_in_free(void *data __UNUSED__,
11474                                      void      *ev)
11475 {
11476    E_Event_Border_Focus_In *e;
11477
11478    e = ev;
11479    e_object_unref(E_OBJECT(e->border));
11480    E_FREE(e);
11481 }
11482
11483 static void
11484 _e_border_event_border_focus_out_free(void *data __UNUSED__,
11485                                       void      *ev)
11486 {
11487    E_Event_Border_Focus_Out *e;
11488
11489    e = ev;
11490    e_object_unref(E_OBJECT(e->border));
11491    E_FREE(e);
11492 }
11493
11494 static void
11495 _e_border_event_border_property_free(void *data __UNUSED__,
11496                                      void      *ev)
11497 {
11498    E_Event_Border_Property *e;
11499
11500    e = ev;
11501    e_object_unref(E_OBJECT(e->border));
11502    E_FREE(e);
11503 }
11504
11505 static void
11506 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
11507                                        void      *ev)
11508 {
11509    E_Event_Border_Fullscreen *e;
11510
11511    e = ev;
11512 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
11513    e_object_unref(E_OBJECT(e->border));
11514    E_FREE(e);
11515 }
11516
11517 static void
11518 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
11519                                          void      *ev)
11520 {
11521    E_Event_Border_Unfullscreen *e;
11522
11523    e = ev;
11524 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
11525    e_object_unref(E_OBJECT(e->border));
11526    E_FREE(e);
11527 }
11528
11529 #ifdef _F_ZONE_WINDOW_ROTATION_
11530 static void
11531 _e_border_event_border_rotation_free(void *data __UNUSED__,
11532                                      void      *ev)
11533 {
11534    E_Event_Border_Rotation *e;
11535
11536    e = ev;
11537    e_object_unref(E_OBJECT(e->border));
11538    E_FREE(e);
11539 }
11540 #endif
11541
11542 static void
11543 _e_border_zone_update(E_Border *bd)
11544 {
11545    E_Container *con;
11546    Eina_List *l;
11547    E_Zone *zone;
11548
11549    /* still within old zone - leave it there */
11550    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
11551                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
11552 #if _F_BORDER_CLIP_TO_ZONE_
11553      {
11554         _e_border_shape_input_clip_to_zone(bd);
11555         return;
11556      }
11557 #else
11558      return;
11559 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
11560    /* find a new zone */
11561    con = bd->zone->container;
11562    EINA_LIST_FOREACH(con->zones, l, zone)
11563      {
11564         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
11565                          zone->x, zone->y, zone->w, zone->h))
11566           {
11567              e_border_zone_set(bd, zone);
11568 #if _F_BORDER_CLIP_TO_ZONE_
11569              _e_border_shape_input_clip_to_zone(bd);
11570 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
11571              return;
11572           }
11573      }
11574 }
11575
11576 static int
11577 _e_border_resize_begin(E_Border *bd)
11578 {
11579    if (!bd->lock_user_stacking)
11580      {
11581         if (e_config->border_raise_on_mouse_action)
11582           e_border_raise(bd);
11583      }
11584    if ((bd->shaded) || (bd->shading) ||
11585        (bd->fullscreen) || (bd->lock_user_size))
11586      return 0;
11587
11588    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
11589      {
11590         grabbed = 0;
11591         return 0;
11592      }
11593
11594    if (bd->client.netwm.sync.request)
11595      {
11596         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
11597         bd->client.netwm.sync.serial = 1;
11598         bd->client.netwm.sync.wait = 0;
11599         bd->client.netwm.sync.send_time = ecore_loop_time_get();
11600      }
11601
11602    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
11603
11604    bdresize = bd;
11605    return 1;
11606 }
11607
11608 static int
11609 _e_border_resize_end(E_Border *bd)
11610 {
11611    if (grabbed)
11612      {
11613         e_grabinput_release(bd->win, bd->win);
11614         grabbed = 0;
11615      }
11616    if (bd->client.netwm.sync.alarm)
11617      {
11618         E_Border_Pending_Move_Resize *pnd;
11619
11620         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
11621         bd->client.netwm.sync.alarm = 0;
11622         /* resize to last geometry if sync alarm for it was not yet handled */
11623         if (bd->pending_move_resize)
11624           {
11625              bd->changed = 1;
11626              bd->changes.pos = 1;
11627              bd->changes.size = 1;
11628              _e_border_client_move_resize_send(bd);
11629           }
11630
11631         EINA_LIST_FREE(bd->pending_move_resize, pnd)
11632           E_FREE(pnd);
11633      }
11634
11635    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
11636
11637    bdresize = NULL;
11638
11639    /* If this border was maximized, we need to unset Maximized state or
11640     * on restart, E still thinks it's maximized */
11641    if (bd->maximized != E_MAXIMIZE_NONE)
11642      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
11643                                   bd->maximized & E_MAXIMIZE_NONE);
11644    return 1;
11645 }
11646
11647 static void
11648 _e_border_resize_update(E_Border *bd)
11649 {
11650    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
11651 }
11652
11653 static int
11654 _e_border_move_begin(E_Border *bd)
11655 {
11656    if (!bd->lock_user_stacking)
11657      {
11658         if (e_config->border_raise_on_mouse_action)
11659           e_border_raise(bd);
11660      }
11661    if ((bd->fullscreen) || (bd->lock_user_location))
11662      return 0;
11663
11664    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
11665      {
11666         grabbed = 0;
11667         return 0;
11668      }
11669 #if 0
11670    if (bd->client.netwm.sync.request)
11671      {
11672         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
11673         bd->client.netwm.sync.serial = 0;
11674         bd->client.netwm.sync.wait = 0;
11675         bd->client.netwm.sync.time = ecore_loop_time_get();
11676      }
11677 #endif
11678    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
11679
11680    bdmove = bd;
11681    return 1;
11682 }
11683
11684 static int
11685 _e_border_move_end(E_Border *bd)
11686 {
11687    if (grabbed)
11688      {
11689         e_grabinput_release(bd->win, bd->win);
11690         grabbed = 0;
11691      }
11692 #if 0
11693    if (bd->client.netwm.sync.alarm)
11694      {
11695         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
11696         bd->client.netwm.sync.alarm = 0;
11697      }
11698 #endif
11699    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
11700
11701    bdmove = NULL;
11702    return 1;
11703 }
11704
11705 static void
11706 _e_border_move_update(E_Border *bd)
11707 {
11708    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
11709 }
11710
11711 static Eina_Bool
11712 _e_border_cb_ping_poller(void *data)
11713 {
11714    E_Border *bd;
11715
11716    bd = data;
11717    if (bd->ping_ok)
11718      {
11719         if (bd->hung)
11720           {
11721              bd->hung = 0;
11722              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
11723              if (bd->kill_timer)
11724                {
11725                   ecore_timer_del(bd->kill_timer);
11726                   bd->kill_timer = NULL;
11727                }
11728           }
11729      }
11730    else
11731      {
11732         /* if time between last ping and now is greater
11733          * than half the ping interval... */
11734         if ((ecore_loop_time_get() - bd->ping) >
11735             ((e_config->ping_clients_interval *
11736               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
11737           {
11738              if (!bd->hung)
11739                {
11740                   bd->hung = 1;
11741                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
11742                   /* FIXME: if below dialog is up - hide it now */
11743                }
11744              if (bd->delete_requested)
11745                {
11746                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
11747                   e_border_act_kill_begin(bd);
11748                }
11749           }
11750      }
11751    bd->ping_poller = NULL;
11752    e_border_ping(bd);
11753    return ECORE_CALLBACK_CANCEL;
11754 }
11755
11756 static Eina_Bool
11757 _e_border_cb_kill_timer(void *data)
11758 {
11759    E_Border *bd;
11760
11761    bd = data;
11762 // dont wait until it's hung -
11763 //   if (bd->hung)
11764 //     {
11765         if (bd->client.netwm.pid > 1)
11766           kill(bd->client.netwm.pid, SIGKILL);
11767 //     }
11768    bd->kill_timer = NULL;
11769    return ECORE_CALLBACK_CANCEL;
11770 }
11771
11772 static void
11773 _e_border_pointer_resize_begin(E_Border *bd)
11774 {
11775    switch (bd->resize_mode)
11776      {
11777       case RESIZE_TL:
11778         e_pointer_type_push(bd->pointer, bd, "resize_tl");
11779         break;
11780
11781       case RESIZE_T:
11782         e_pointer_type_push(bd->pointer, bd, "resize_t");
11783         break;
11784
11785       case RESIZE_TR:
11786         e_pointer_type_push(bd->pointer, bd, "resize_tr");
11787         break;
11788
11789       case RESIZE_R:
11790         e_pointer_type_push(bd->pointer, bd, "resize_r");
11791         break;
11792
11793       case RESIZE_BR:
11794         e_pointer_type_push(bd->pointer, bd, "resize_br");
11795         break;
11796
11797       case RESIZE_B:
11798         e_pointer_type_push(bd->pointer, bd, "resize_b");
11799         break;
11800
11801       case RESIZE_BL:
11802         e_pointer_type_push(bd->pointer, bd, "resize_bl");
11803         break;
11804
11805       case RESIZE_L:
11806         e_pointer_type_push(bd->pointer, bd, "resize_l");
11807         break;
11808      }
11809 }
11810
11811 static void
11812 _e_border_pointer_resize_end(E_Border *bd)
11813 {
11814    switch (bd->resize_mode)
11815      {
11816       case RESIZE_TL:
11817         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
11818         break;
11819
11820       case RESIZE_T:
11821         e_pointer_type_pop(bd->pointer, bd, "resize_t");
11822         break;
11823
11824       case RESIZE_TR:
11825         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
11826         break;
11827
11828       case RESIZE_R:
11829         e_pointer_type_pop(bd->pointer, bd, "resize_r");
11830         break;
11831
11832       case RESIZE_BR:
11833         e_pointer_type_pop(bd->pointer, bd, "resize_br");
11834         break;
11835
11836       case RESIZE_B:
11837         e_pointer_type_pop(bd->pointer, bd, "resize_b");
11838         break;
11839
11840       case RESIZE_BL:
11841         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
11842         break;
11843
11844       case RESIZE_L:
11845         e_pointer_type_pop(bd->pointer, bd, "resize_l");
11846         break;
11847      }
11848 }
11849
11850 static void
11851 _e_border_pointer_move_begin(E_Border *bd)
11852 {
11853    e_pointer_type_push(bd->pointer, bd, "move");
11854 }
11855
11856 static void
11857 _e_border_pointer_move_end(E_Border *bd)
11858 {
11859    e_pointer_type_pop(bd->pointer, bd, "move");
11860 }
11861
11862 static Eina_List *_e_border_hooks = NULL;
11863 static int _e_border_hooks_delete = 0;
11864 static int _e_border_hooks_walking = 0;
11865
11866 static void
11867 _e_border_hooks_clean(void)
11868 {
11869    Eina_List *l, *ln;
11870    E_Border_Hook *bh;
11871
11872    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
11873      {
11874         if (bh->delete_me)
11875           {
11876              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
11877              free(bh);
11878           }
11879      }
11880 }
11881
11882 static void
11883 _e_border_hook_call(E_Border_Hook_Point hookpoint,
11884                     void               *bd)
11885 {
11886    Eina_List *l;
11887    E_Border_Hook *bh;
11888
11889    _e_border_hooks_walking++;
11890    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
11891      {
11892         if (bh->delete_me) continue;
11893         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
11894      }
11895    _e_border_hooks_walking--;
11896    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
11897      _e_border_hooks_clean();
11898 }
11899
11900 EAPI E_Border_Hook *
11901 e_border_hook_add(E_Border_Hook_Point               hookpoint,
11902                   void                              (*func)(void *data,
11903                                               void *bd),
11904                   void                             *data)
11905 {
11906    E_Border_Hook *bh;
11907
11908    bh = E_NEW(E_Border_Hook, 1);
11909    if (!bh) return NULL;
11910    bh->hookpoint = hookpoint;
11911    bh->func = func;
11912    bh->data = data;
11913    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
11914    return bh;
11915 }
11916
11917 EAPI void
11918 e_border_hook_del(E_Border_Hook *bh)
11919 {
11920    bh->delete_me = 1;
11921    if (_e_border_hooks_walking == 0)
11922      {
11923         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
11924         free(bh);
11925      }
11926    else
11927      _e_border_hooks_delete++;
11928 }
11929
11930 EAPI void
11931 e_border_focus_track_freeze(void)
11932 {
11933    focus_track_frozen++;
11934 }
11935
11936 EAPI void
11937 e_border_focus_track_thaw(void)
11938 {
11939    focus_track_frozen--;
11940 }
11941
11942 EAPI E_Border *
11943 e_border_under_pointer_get(E_Desk   *desk,
11944                            E_Border *exclude)
11945 {
11946    E_Border *bd = NULL, *cbd;
11947    Eina_List *l;
11948    int x, y;
11949
11950    /* We need to ensure that we can get the container window for the
11951     * zone of either the given desk or the desk of the excluded
11952     * window, so return if neither is given */
11953    if (desk)
11954      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
11955    else if (exclude)
11956      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
11957    else
11958      return NULL;
11959
11960    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
11961      {
11962         if (!cbd) continue;
11963         /* If a border was specified which should be excluded from the list
11964          * (because it will be closed shortly for example), skip */
11965         if ((exclude) && (cbd == exclude)) continue;
11966         if ((desk) && (cbd->desk != desk)) continue;
11967         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
11968           continue;
11969         /* If the layer is higher, the position of the window is higher
11970          * (always on top vs always below) */
11971         if (!bd || (cbd->layer > bd->layer))
11972           {
11973              bd = cbd;
11974              break;
11975           }
11976      }
11977    return bd;
11978 }
11979
11980 static Eina_Bool
11981 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
11982 {
11983    if (warp_to)
11984      {
11985         int x, y;
11986         double spd;
11987
11988         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
11989         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
11990             (y - warp_y) > 5 || (y - warp_y) < -5)
11991           {
11992              /* User moved the mouse, so stop warping */
11993              warp_to = 0;
11994              goto cleanup;
11995           }
11996
11997         /* We just use the same warp speed as configured
11998          * for the windowlist */
11999         spd = e_config->winlist_warp_speed;
12000         x = warp_x;
12001         y = warp_y;
12002         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12003         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12004         if (warp_x == x && warp_y == y)
12005           {
12006              warp_x = warp_to_x;
12007              warp_y = warp_to_y;
12008              warp_to = 0;
12009              goto cleanup;
12010           }
12011         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12012         return ECORE_CALLBACK_RENEW;
12013      }
12014  cleanup:
12015    ecore_timer_del(warp_timer);
12016    warp_timer = NULL;
12017    return ECORE_CALLBACK_CANCEL;
12018 }
12019
12020 EAPI int
12021 e_border_pointer_warp_to_center(E_Border *bd)
12022 {
12023    int x, y;
12024
12025    /* Do not slide pointer when disabled (probably breaks focus
12026     * on sloppy/mouse focus but requested by users). */
12027    if (!e_config->pointer_slide) return 0;
12028    /* Only warp the pointer if it is not already in the area of
12029     * the given border */
12030    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12031    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12032        (y >= bd->y) && (y <= (bd->y + bd->h)))
12033      return 0;
12034
12035    warp_to_x = bd->x + (bd->w / 2);
12036    if (warp_to_x < (bd->zone->x + 1))
12037      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12038    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12039      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12040
12041    warp_to_y = bd->y + (bd->h / 2);
12042    if (warp_to_y < (bd->zone->y + 1))
12043      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12044    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12045      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12046
12047    warp_to = 1;
12048    warp_to_win = bd->zone->container->win;
12049    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12050    if (!warp_timer)
12051      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12052    return 1;
12053 }
12054
12055 EAPI void
12056 e_border_comp_hidden_set(E_Border *bd,
12057                          Eina_Bool hidden)
12058 {
12059    E_Border *tmp;
12060    Eina_List *l;
12061
12062    E_OBJECT_CHECK(bd);
12063    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12064
12065    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12066      {
12067        if (hidden)
12068          ecore_x_window_hide(tmp->win);
12069        else
12070          ecore_x_window_show(tmp->win);
12071      }
12072
12073    if (bd->comp_hidden == hidden) return;
12074
12075    bd->comp_hidden = hidden;
12076
12077    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12078      {
12079         ecore_x_composite_window_events_disable(bd->win);
12080         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12081      }
12082    else
12083      {
12084         _e_border_shape_input_rectangle_set(bd);
12085         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12086      }
12087 }
12088
12089 EAPI void
12090 e_border_tmp_input_hidden_push(E_Border *bd)
12091 {
12092    E_Border *tmp;
12093    Eina_List *l;
12094
12095    E_OBJECT_CHECK(bd);
12096    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12097
12098    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12099      e_border_tmp_input_hidden_push(tmp);
12100
12101    bd->tmp_input_hidden++;
12102    if (bd->tmp_input_hidden != 1) return;
12103
12104    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12105      {
12106         ecore_x_composite_window_events_disable(bd->win);
12107         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12108      }
12109    else
12110      {
12111         _e_border_shape_input_rectangle_set(bd);
12112         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12113      }
12114 }
12115
12116 EAPI void
12117 e_border_tmp_input_hidden_pop(E_Border *bd)
12118 {
12119    E_Border *tmp;
12120    Eina_List *l;
12121
12122    E_OBJECT_CHECK(bd);
12123    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12124
12125    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12126      e_border_tmp_input_hidden_pop(tmp);
12127
12128    bd->tmp_input_hidden--;
12129    if (bd->tmp_input_hidden != 0) return;
12130
12131    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12132      {
12133         ecore_x_composite_window_events_disable(bd->win);
12134         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12135      }
12136    else
12137      {
12138         _e_border_shape_input_rectangle_set(bd);
12139         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12140      }
12141 }
12142
12143 EAPI void
12144 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
12145 {
12146    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
12147        ((bd->parent) &&
12148         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
12149          ((bd->parent->focused) &&
12150           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
12151        (just_do_it))
12152      {
12153         if (bd->iconic)
12154           {
12155              if (e_config->clientlist_warp_to_iconified_desktop == 1)
12156                e_desk_show(bd->desk);
12157              
12158              if (!bd->lock_user_iconify)
12159                e_border_uniconify(bd);
12160           }
12161         if ((!bd->iconic) && (!bd->sticky))
12162           e_desk_show(bd->desk);
12163         if (!bd->lock_user_stacking) e_border_raise(bd);
12164         if (!bd->lock_focus_out)
12165           {
12166              /* XXX ooffice does send this request for
12167               config dialogs when the main window gets focus.
12168               causing the pointer to jump back and forth.  */
12169              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
12170                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
12171                ecore_x_pointer_warp(bd->zone->container->win,
12172                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
12173              e_border_focus_set(bd, 1, 1);
12174           }
12175      }
12176 }
12177 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/