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