Enable the pending show for the rotation process.
[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
3768    if (e_config->deiconify_approve)
3769      {
3770         if (!e_object_is_del(E_OBJECT(bd)))
3771           {
3772              bd->client.e.state.deiconify_approve.pending_job = NULL;
3773
3774              ELBF(ELBT_BD, 0, bd->client.win,
3775                   "SEND DEICONIFY_APPROVE. (PENDING_END) ancestor:%x",
3776                   bd->client.win);
3777
3778              ecore_x_client_message32_send(bd->client.win,
3779                                            ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3780                                            ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3781                                            bd->client.win, 0, 0, 0, 0);
3782
3783              bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
3784           }
3785      }
3786 }
3787
3788 static void
3789 _e_border_deiconify_approve_send(E_Border *bd, E_Border *bd_ancestor, Eina_Bool pending_ancestor)
3790 {
3791    if (!bd || !bd_ancestor) return;
3792
3793    if (e_config->deiconify_approve)
3794      {
3795         if (e_config->transient.iconify)
3796           {
3797              Eina_List *l;
3798              E_Border *child;
3799              Eina_List *list = _e_border_sub_borders_new(bd);
3800              EINA_LIST_FOREACH(list, l, child)
3801                {
3802                   Eina_Bool pending = EINA_FALSE;
3803                   Eina_Bool p = EINA_FALSE;
3804
3805 #ifdef _F_ZONE_WINDOW_ROTATION_
3806                   if ((e_config->wm_win_rotation) &&
3807                       ((child->client.e.state.rot.support) ||
3808                        (child->client.e.state.rot.app_set)))
3809                     {
3810                        ELB(ELBT_ROT, "CHECK_DEICONIFY CHILD", child->client.win);
3811                        int rotation = _e_border_rotation_angle_get(bd);
3812                        if (rotation != -1) _e_border_rotation_set_internal(bd, rotation, &pending);
3813                     }
3814 #endif
3815                   if ((pending_ancestor) || (pending)) p = EINA_TRUE;
3816
3817                   _e_border_deiconify_approve_send(child, bd_ancestor, p);
3818                   if (child->client.e.state.deiconify_approve.support)
3819                     {
3820                        if (p)
3821                          {
3822                             ELBF(ELBT_BD, 0, child->client.win,
3823                                  "SEND DEICONIFY_APPROVE. ancestor:%x pending(%d,%d)",
3824                                  bd_ancestor->client.win,
3825                                  pending_ancestor, pending);
3826
3827                             ecore_x_client_message32_send(child->client.win,
3828                                                           ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3829                                                           ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3830                                                           child->client.win, 0, 0, 0, 0);
3831                             child->client.e.state.deiconify_approve.ancestor = bd_ancestor;
3832                             bd_ancestor->client.e.state.deiconify_approve.req_list = eina_list_append(bd_ancestor->client.e.state.deiconify_approve.req_list, child);
3833                          }
3834                        else
3835                          {
3836                             /* queue a deiconify send job to give the chance to other jobs */
3837                             ELBF(ELBT_BD, 0, child->client.win,
3838                                  "SEND DEICONIFY_APPROVE. (PENDING) ancestor:%x",
3839                                  bd_ancestor->client.win);
3840                             child->client.e.state.deiconify_approve.pending_job = ecore_job_add(_e_border_deiconify_approve_send_pending_end, child);
3841                          }
3842                     }
3843                }
3844              eina_list_free(list);
3845           }
3846      }
3847 }
3848
3849 static void
3850 _e_border_deiconify_approve_send_all_transient(E_Border *bd)
3851 {
3852    Eina_Bool pending = EINA_FALSE;
3853
3854    if (e_config->deiconify_approve)
3855      {
3856 #ifdef _F_ZONE_WINDOW_ROTATION_
3857         if ((e_config->wm_win_rotation) &&
3858             ((bd->client.e.state.rot.support) ||
3859              (bd->client.e.state.rot.app_set)))
3860           {
3861              ELB(ELBT_ROT, "CHECK_DEICONIFY", bd->client.win);
3862              int rotation = _e_border_rotation_angle_get(bd);
3863              if (rotation != -1) _e_border_rotation_set_internal(bd, rotation, &pending);
3864           }
3865 #endif
3866
3867         if (e_config->transient.iconify)
3868           {
3869              _e_border_deiconify_approve_send(bd, bd, pending);
3870           }
3871
3872         if (bd->client.e.state.deiconify_approve.support)
3873           {
3874              if (!pending)
3875                {
3876                   ELBF(ELBT_BD, 0, bd->client.win, "SEND DEICONIFY_APPROVE.");
3877                   ecore_x_client_message32_send(bd->client.win,
3878                                                 ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3879                                                 ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3880                                                 bd->client.win, 0, 0, 0, 0);
3881                   bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
3882                }
3883              else
3884                {
3885                   /* queue a deiconify send job to give the chance to other jobs */
3886                   ELBF(ELBT_BD, 0, bd->client.win, "SEND DEICONIFY_APPROVE. (PENDING)");
3887                   bd->client.e.state.deiconify_approve.pending_job = ecore_job_add(_e_border_deiconify_approve_send_pending_end, bd);
3888                }
3889           }
3890      }
3891 }
3892 #endif
3893
3894 EAPI void
3895 e_border_uniconify(E_Border *bd)
3896 {
3897    E_Desk *desk;
3898    E_Event_Border_Uniconify *ev;
3899    unsigned int iconic;
3900
3901    E_OBJECT_CHECK(bd);
3902    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3903
3904 #ifdef _F_DEICONIFY_APPROVE_
3905    if (e_config->deiconify_approve)
3906      {
3907         if (bd->client.e.state.deiconify_approve.support)
3908           {
3909              if (bd->client.e.state.deiconify_approve.wait_timer)
3910                {
3911                   ELB(ELBT_BD, "DEICONIFY_APPROVE WAIT_TIMER is already running", bd->client.win);
3912                   return;
3913                }
3914              if (bd->client.e.state.deiconify_approve.render_done == 0)
3915                {
3916                   ELB(ELBT_BD, "DEICONIFY_APPROVE to all transient", bd->client.win);
3917                   _e_border_deiconify_approve_send_all_transient(bd);
3918                   return;
3919                }
3920           }
3921         bd->client.e.state.deiconify_approve.render_done = 0;
3922      }
3923 #endif
3924
3925 #if _F_ZONE_WINDOW_ROTATION_
3926    if (!bd->client.win)
3927      {
3928         ELB(ELBT_DFT, "ERR! obj is already deleted", bd->client.win);
3929         return;
3930      }
3931 #endif
3932
3933    if (bd->shading) return;
3934    ecore_x_window_shadow_tree_flush();
3935    e_border_show(bd);
3936    if (bd->iconic)
3937      {
3938         bd->iconic = 0;
3939         if (bd->fullscreen) bd->desk->fullscreen_borders++;
3940         desk = e_desk_current_get(bd->desk->zone);
3941 #ifdef _F_USE_EXTENDED_ICONIFY_
3942         if (e_manager_comp_evas_get(bd->zone->container->manager))
3943           {
3944              if (bd->await_hide_event > 0)
3945                bd->await_hide_event--;
3946           }
3947 #endif
3948         e_border_desk_set(bd, desk);
3949         e_border_raise(bd);
3950         edje_object_signal_emit(bd->bg_object, "e,action,uniconify", "e");
3951      }
3952    iconic = 0;
3953    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
3954
3955    ev = E_NEW(E_Event_Border_Uniconify, 1);
3956    ev->border = bd;
3957    e_object_ref(E_OBJECT(bd));
3958 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_uniconify_event");
3959    ecore_event_add(E_EVENT_BORDER_UNICONIFY, ev, _e_border_event_border_uniconify_free, NULL);
3960
3961    if (e_config->transient.iconify)
3962      {
3963         Eina_List *l;
3964         E_Border *child;
3965         Eina_List *list = _e_border_sub_borders_new(bd);
3966
3967         EINA_LIST_FOREACH(list, l, child)
3968           {
3969              e_border_uniconify(child);
3970           }
3971         eina_list_free(list);
3972      }
3973    e_remember_update(bd);
3974 }
3975
3976 EAPI void
3977 e_border_stick(E_Border *bd)
3978 {
3979    E_Event_Border_Stick *ev;
3980
3981    E_OBJECT_CHECK(bd);
3982    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3983    if (bd->sticky) return;
3984    bd->sticky = 1;
3985    e_hints_window_sticky_set(bd, 1);
3986    e_border_show(bd);
3987
3988    if (e_config->transient.desktop)
3989      {
3990         Eina_List *l;
3991         E_Border *child;
3992         Eina_List *list = _e_border_sub_borders_new(bd);
3993
3994         EINA_LIST_FOREACH(list, l, child)
3995           {
3996              child->sticky = 1;
3997              e_hints_window_sticky_set(child, 1);
3998              e_border_show(child);
3999           }
4000         eina_list_free(list);
4001      }
4002
4003    edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
4004    ev = E_NEW(E_Event_Border_Stick, 1);
4005    ev->border = bd;
4006    e_object_ref(E_OBJECT(bd));
4007 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_stick_event");
4008    ecore_event_add(E_EVENT_BORDER_STICK, ev, _e_border_event_border_stick_free, NULL);
4009    e_remember_update(bd);
4010 }
4011
4012 EAPI void
4013 e_border_unstick(E_Border *bd)
4014 {
4015    E_Event_Border_Unstick *ev;
4016
4017    E_OBJECT_CHECK(bd);
4018    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4019    /* Set the desk before we unstick the border */
4020    if (!bd->sticky) return;
4021    bd->sticky = 0;
4022    e_hints_window_sticky_set(bd, 0);
4023
4024    if (e_config->transient.desktop)
4025      {
4026         Eina_List *l;
4027         E_Border *child;
4028         Eina_List *list = _e_border_sub_borders_new(bd);
4029
4030         EINA_LIST_FOREACH(list, l, child)
4031           {
4032              child->sticky = 0;
4033              e_hints_window_sticky_set(child, 0);
4034           }
4035         eina_list_free(list);
4036      }
4037
4038    edje_object_signal_emit(bd->bg_object, "e,state,unsticky", "e");
4039    ev = E_NEW(E_Event_Border_Unstick, 1);
4040    ev->border = bd;
4041    e_object_ref(E_OBJECT(bd));
4042 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_unstick_event");
4043    ecore_event_add(E_EVENT_BORDER_UNSTICK, ev, _e_border_event_border_unstick_free, NULL);
4044
4045    e_border_desk_set(bd, e_desk_current_get(bd->zone));
4046    e_remember_update(bd);
4047 }
4048
4049 EAPI void
4050 e_border_pinned_set(E_Border *bd,
4051                     int       set)
4052 {
4053    int layer;
4054    int stacking;
4055
4056    if (bd)
4057      {
4058         bd->borderless = set;
4059         bd->user_skip_winlist = set;
4060         if (set)
4061           {
4062              layer = 50;
4063              stacking = E_STACKING_BELOW;
4064           }
4065         else
4066           {
4067              layer = 100;
4068              stacking = E_STACKING_NONE;
4069           }
4070
4071         e_border_layer_set(bd, layer);
4072         e_hints_window_stacking_set(bd, stacking);
4073
4074         bd->client.border.changed = 1;
4075         bd->changed = 1;
4076      }
4077 }
4078
4079 EAPI E_Border *
4080 e_border_find_by_client_window(Ecore_X_Window win)
4081 {
4082    E_Border *bd;
4083
4084    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4085    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4086        (bd->client.win == win))
4087      return bd;
4088    return NULL;
4089 }
4090
4091 EAPI E_Border *
4092 e_border_find_all_by_client_window(Ecore_X_Window win)
4093 {
4094    E_Border *bd;
4095
4096    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4097    if ((bd) && (bd->client.win == win))
4098      return bd;
4099    return NULL;
4100 }
4101
4102 EAPI E_Border *
4103 e_border_find_by_frame_window(Ecore_X_Window win)
4104 {
4105    E_Border *bd;
4106
4107    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4108    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4109        (bd->bg_win == win))
4110      return bd;
4111    return NULL;
4112 }
4113
4114 EAPI E_Border *
4115 e_border_find_by_window(Ecore_X_Window win)
4116 {
4117    E_Border *bd;
4118
4119    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4120    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4121        (bd->win == win))
4122      return bd;
4123    return NULL;
4124 }
4125
4126 EAPI E_Border *
4127 e_border_find_by_alarm(Ecore_X_Sync_Alarm al)
4128 {
4129    Eina_List *l;
4130    E_Border *bd;
4131
4132    EINA_LIST_FOREACH(borders, l, bd)
4133      {
4134         if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4135             (bd->client.netwm.sync.alarm == al))
4136           return bd;
4137      }
4138    return NULL;
4139 }
4140
4141 EAPI E_Border *
4142 e_border_focused_get(void)
4143 {
4144    return focused;
4145 }
4146
4147 static void
4148 _e_border_shape_input_rectangle_set(E_Border* bd)
4149 {
4150    if (!bd) return;
4151
4152    if ((bd->visible) && (bd->shaped_input))
4153      {
4154         Ecore_X_Rectangle rects[4];
4155         Ecore_X_Window twin, twin2;
4156         int x, y;
4157
4158         twin = ecore_x_window_override_new(bd->zone->container->scratch_win,
4159                                            0, 0, bd->w, bd->h);
4160         rects[0].x = 0;
4161         rects[0].y = 0;
4162         rects[0].width = bd->w;
4163         rects[0].height = bd->client_inset.t;
4164         rects[1].x = 0;
4165         rects[1].y = bd->client_inset.t;
4166         rects[1].width = bd->client_inset.l;
4167         rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
4168         rects[2].x = bd->w - bd->client_inset.r;
4169         rects[2].y = bd->client_inset.t;
4170         rects[2].width = bd->client_inset.r;
4171         rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
4172         rects[3].x = 0;
4173         rects[3].y = bd->h - bd->client_inset.b;
4174         rects[3].width = bd->w;
4175         rects[3].height = bd->client_inset.b;
4176         ecore_x_window_shape_input_rectangles_set(twin, rects, 4);
4177
4178         twin2 = ecore_x_window_override_new
4179            (bd->zone->container->scratch_win, 0, 0,
4180                bd->w - bd->client_inset.l - bd->client_inset.r,
4181                bd->h - bd->client_inset.t - bd->client_inset.b);
4182         x = 0;
4183         y = 0;
4184         if ((bd->shading) || (bd->shaded))
4185           {
4186              if (bd->shade.dir == E_DIRECTION_UP)
4187                 y = bd->h - bd->client_inset.t - bd->client_inset.b -
4188                 bd->client.h;
4189              else if (bd->shade.dir == E_DIRECTION_LEFT)
4190                 x = bd->w - bd->client_inset.l - bd->client_inset.r -
4191                 bd->client.w;
4192           }
4193         ecore_x_window_shape_input_window_set_xy(twin2, bd->client.win,
4194                                                  x, y);
4195         ecore_x_window_shape_input_rectangle_clip(twin2, 0, 0,
4196                                                   bd->w - bd->client_inset.l - bd->client_inset.r,
4197                                                   bd->h - bd->client_inset.t - bd->client_inset.b);
4198         ecore_x_window_shape_input_window_add_xy(twin, twin2,
4199                                                  bd->client_inset.l,
4200                                                  bd->client_inset.t);
4201         ecore_x_window_shape_input_window_set(bd->win, twin);
4202         ecore_x_window_free(twin2);
4203         ecore_x_window_free(twin);
4204      }
4205    else
4206      {
4207         if (bd->visible) // not shaped input
4208           {
4209              if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
4210                 ecore_x_composite_window_events_enable(bd->win);
4211              else
4212                 ecore_x_composite_window_events_disable(bd->win);
4213           }
4214         else
4215           {
4216              if (!e_manager_comp_evas_get(bd->zone->container->manager))
4217                 ecore_x_composite_window_events_enable(bd->win);
4218              else
4219                 ecore_x_composite_window_events_disable(bd->win);
4220           }
4221      }
4222 }
4223
4224 EAPI void
4225 e_border_idler_before(void)
4226 {
4227    Eina_List *ml, *cl;
4228    E_Manager *man;
4229    E_Container *con;
4230
4231    if (!borders)
4232      return;
4233
4234    EINA_LIST_FOREACH(e_manager_list(), ml, man)
4235      {
4236         EINA_LIST_FOREACH(man->containers, cl, con)
4237           {
4238              E_Border_List *bl;
4239              E_Border *bd;
4240
4241              // pass 1 - eval0. fetch properties on new or on change and
4242              // call hooks to decide what to do - maybe move/resize
4243              bl = e_container_border_list_last(con);
4244              while ((bd = e_container_border_list_prev(bl)))
4245                {
4246                   if (bd->changed) _e_border_eval0(bd);
4247                }
4248              e_container_border_list_free(bl);
4249
4250              // layout hook - this is where a hook gets to figure out what to
4251              // do if anything.
4252              _e_border_container_layout_hook(con);
4253
4254              // pass 2 - show windows needing show
4255              bl = e_container_border_list_last(con);
4256              while ((bd = e_container_border_list_prev(bl)))
4257                {
4258                   if ((bd->changes.visible) && (bd->visible) &&
4259                       (!bd->new_client) && (!bd->changes.pos) &&
4260                       (!bd->changes.size))
4261                     {
4262                        _e_border_show(bd);
4263                        bd->changes.visible = 0;
4264                     }
4265                }
4266              e_container_border_list_free(bl);
4267
4268              // pass 3 - hide windows needing hide and eval (main eval)
4269              bl = e_container_border_list_first(con);
4270              while ((bd = e_container_border_list_next(bl)))
4271                {
4272                   if (e_object_is_del(E_OBJECT(bd))) continue;
4273
4274                   if ((bd->changes.visible) && (!bd->visible))
4275                     {
4276                        _e_border_hide(bd);
4277                        bd->changes.visible = 0;
4278                     }
4279
4280                   if (bd->changed) _e_border_eval(bd);
4281
4282                   if ((bd->changes.visible) && (bd->visible))
4283                     {
4284                        _e_border_show(bd);
4285                        bd->changes.visible = 0;
4286                     }
4287                }
4288              e_container_border_list_free(bl);
4289           }
4290      }
4291
4292    if (focus_next)
4293      {
4294         E_Border *bd = NULL, *bd2;
4295
4296         EINA_LIST_FREE(focus_next, bd2)
4297           if ((!bd) && (bd2->visible)) bd = bd2;
4298
4299         if (!bd)
4300           {
4301              /* TODO revert focus when lost here ? */
4302              return;
4303           }
4304 #if 0
4305         if (bd == focused)
4306           {
4307              /* already focused. but anyway dont be so strict, this
4308                 fcks up illume setting focus on internal windows */
4309              return;
4310           }
4311 #endif
4312         
4313         focus_time = ecore_x_current_time_get();
4314
4315         focusing = bd;
4316
4317         if ((bd->client.icccm.take_focus) &&
4318             (bd->client.icccm.accepts_focus))
4319           {
4320              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
4321              /* TODO what if the client didn't take focus ? */
4322           }
4323         else if (!bd->client.icccm.accepts_focus)
4324           {
4325              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
4326           }
4327         else if (!bd->client.icccm.take_focus)
4328           {
4329              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
4330              /* e_border_focus_set(bd, 1, 0); */
4331           }
4332      }
4333
4334 #ifdef _F_ZONE_WINDOW_ROTATION_
4335    if ((e_config->wm_win_rotation) &&
4336        (rot.fetch))
4337      {
4338         Ecore_X_Event_Client_Message *msg = NULL;
4339         Ecore_X_Atom t = 0;
4340         EINA_LIST_FREE(rot.msgs, msg)
4341           {
4342              t = msg->message_type;
4343              if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)
4344                {
4345                   if ((rot.vkbd_ctrl_win) &&
4346                       ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) &&
4347                       (rot.vkbd))
4348                     {
4349                        ELB(ELBT_BD, "GET KBD_ON_PREPARE_DONE", rot.vkbd_ctrl_win);
4350                        if (rot.vkbd_show_prepare_timer)
4351                          _e_border_vkbd_show(rot.vkbd);
4352                        else
4353                          ELB(ELBT_BD, "GET KBD_ON_PREPARE_DONE but skip", rot.vkbd_ctrl_win);
4354                     }
4355                }
4356              else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE)
4357                {
4358                   if ((rot.vkbd_ctrl_win) &&
4359                       ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) &&
4360                       (rot.vkbd))
4361                     {
4362                        ELB(ELBT_BD, "GET KBD_OFF_PREPARE_DONE", rot.vkbd_ctrl_win);
4363                        if (rot.vkbd_hide_prepare_timer)
4364                          {
4365                             _e_border_vkbd_hide(rot.vkbd);
4366                             rot.vkbd_hide_prepare_timer = NULL;
4367                             e_object_unref(E_OBJECT(rot.vkbd));
4368                          }
4369                        else
4370                          ELB(ELBT_BD, "GET KBD_OFF_PREPARE_DONE but skip", rot.vkbd_ctrl_win);
4371                     }
4372                }
4373              else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)
4374                {
4375                   rot.vkbd_ctrl_win = msg->data.l[0];
4376                   ELB(ELBT_BD, "SET KBD_CONTROL_WIN", rot.vkbd_ctrl_win);
4377                }
4378              else if (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE)
4379                {
4380                   if ((rot.vkbd_ctrl_win) &&
4381                       (rot.vkbd_ctrl_win == (Ecore_X_Window)msg->data.l[0]))
4382                     {
4383                        ELB(ELBT_ROT, "GET ROT_PREPARE_DONE", rot.vkbd_ctrl_win);
4384                        E_Manager *m = e_manager_current_get();
4385                        E_Zone *zone = NULL;
4386                        if (m) zone = e_util_zone_current_get(m);
4387                        if ((zone) && (rot.wait_prepare_done))
4388                          {
4389                             if (rot.list)
4390                               {
4391                                  _e_border_rotation_change_request(zone);
4392                                  if (rot.prepare_timer)
4393                                    ecore_timer_del(rot.prepare_timer);
4394                                  rot.prepare_timer = NULL;
4395                                  rot.wait_prepare_done = EINA_FALSE;
4396
4397                               }
4398                          }
4399                     }
4400                }
4401              E_FREE(msg);
4402           }
4403         rot.msgs = NULL;
4404         rot.fetch = EINA_FALSE;
4405      }
4406 #endif
4407 }
4408
4409 EAPI Eina_List *
4410 e_border_client_list(void)
4411 {
4412    /* FIXME: This should be a somewhat ordered list */
4413    return borders;
4414 }
4415
4416 static Ecore_X_Window action_input_win = 0;
4417 static E_Border *action_border = NULL;
4418 static Ecore_Event_Handler *action_handler_key = NULL;
4419 static Ecore_Event_Handler *action_handler_mouse = NULL;
4420 static Ecore_Timer *action_timer = NULL;
4421 static Ecore_X_Rectangle action_orig;
4422
4423 static void
4424 _e_border_show(E_Border *bd)
4425 {
4426    Eina_List *l;
4427    E_Border *tmp;
4428
4429    ecore_evas_show(bd->bg_ecore_evas);
4430
4431    if (bd->post_job)
4432      {
4433         bd->post_show = 1;
4434         return;
4435      }
4436
4437    if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
4438      {
4439         _e_border_shape_input_rectangle_set(bd);
4440         // not anymore
4441         //      ecore_x_composite_window_events_enable(bd->win);
4442         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
4443      }
4444
4445    ecore_x_window_show(bd->win);
4446
4447    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
4448      ecore_x_window_show(tmp->win);
4449 }
4450
4451 static void
4452 _e_border_hide(E_Border *bd)
4453 {
4454    E_Border *tmp;
4455    Eina_List *l;
4456
4457    if (!e_manager_comp_evas_get(bd->zone->container->manager))
4458      {
4459         ecore_x_window_hide(bd->win);
4460         ecore_evas_hide(bd->bg_ecore_evas);
4461
4462         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
4463           ecore_x_window_hide(tmp->win);
4464      }
4465    else
4466      {
4467         ecore_x_composite_window_events_disable(bd->win);
4468         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
4469      }
4470 }
4471
4472 static int
4473 _e_border_action_input_win_del(void)
4474 {
4475    if (!action_input_win)
4476      return 0;
4477
4478    e_grabinput_release(action_input_win, action_input_win);
4479    ecore_x_window_free(action_input_win);
4480    action_input_win = 0;
4481    return 1;
4482 }
4483
4484 static int
4485 _e_border_action_input_win_new(E_Border *bd)
4486 {
4487    if (!action_input_win)
4488      {
4489         Ecore_X_Window parent = bd->zone->container->win;
4490         action_input_win = ecore_x_window_input_new(parent, 0, 0, 1, 1);
4491         if (!action_input_win)
4492           return 0;
4493      }
4494
4495    ecore_x_window_show(action_input_win);
4496    if (e_grabinput_get(action_input_win, 0, action_input_win))
4497      return 1;
4498
4499    _e_border_action_input_win_del();
4500    return 0;
4501 }
4502
4503 static void
4504 _e_border_action_finish(void)
4505 {
4506    _e_border_action_input_win_del();
4507
4508    if (action_timer)
4509      {
4510         ecore_timer_del(action_timer);
4511         action_timer = NULL;
4512      }
4513
4514    if (action_handler_key)
4515      {
4516         ecore_event_handler_del(action_handler_key);
4517         action_handler_key = NULL;
4518      }
4519
4520    if (action_handler_mouse)
4521      {
4522         ecore_event_handler_del(action_handler_mouse);
4523         action_handler_mouse = NULL;
4524      }
4525
4526    action_border = NULL;
4527 }
4528
4529 static void
4530 _e_border_action_init(E_Border *bd)
4531 {
4532    action_orig.x = bd->x;
4533    action_orig.y = bd->y;
4534    action_orig.width = bd->w;
4535    action_orig.height = bd->h;
4536
4537    action_border = bd;
4538 }
4539
4540 static void
4541 _e_border_action_restore_orig(E_Border *bd)
4542 {
4543    if (action_border != bd)
4544      return;
4545
4546    e_border_move_resize(bd, action_orig.x, action_orig.y, action_orig.width, action_orig.height);
4547 }
4548
4549 static int
4550 _e_border_key_down_modifier_apply(int modifier,
4551                                   int value)
4552 {
4553    if (modifier & ECORE_EVENT_MODIFIER_CTRL)
4554      return value * 2;
4555    else if (modifier & ECORE_EVENT_MODIFIER_ALT)
4556      {
4557         value /= 2;
4558         if (value)
4559           return value;
4560         else
4561           return 1;
4562      }
4563
4564    return value;
4565 }
4566
4567 static Eina_Bool
4568 _e_border_action_move_timeout(void *data __UNUSED__)
4569 {
4570    _e_border_move_end(action_border);
4571    _e_border_action_finish();
4572    return ECORE_CALLBACK_CANCEL;
4573 }
4574
4575 static void
4576 _e_border_action_move_timeout_add(void)
4577 {
4578    if (action_timer)
4579      ecore_timer_del(action_timer);
4580    action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_move_timeout, NULL);
4581 }
4582
4583 static Eina_Bool
4584 _e_border_move_key_down(void *data __UNUSED__,
4585                         int type   __UNUSED__,
4586                         void      *event)
4587 {
4588    Ecore_Event_Key *ev = event;
4589    int x, y;
4590
4591    if (ev->event_window != action_input_win)
4592      return ECORE_CALLBACK_PASS_ON;
4593    if (!action_border)
4594      {
4595         fputs("ERROR: no action_border!\n", stderr);
4596         goto stop;
4597      }
4598
4599    x = action_border->x;
4600    y = action_border->y;
4601
4602    if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
4603      y -= _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dy);
4604    else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
4605      y += _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dy);
4606    else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
4607      x -= _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dx);
4608    else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
4609      x += _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dx);
4610    else if (strcmp(ev->key, "Return") == 0)
4611      goto stop;
4612    else if (strcmp(ev->key, "Escape") == 0)
4613      {
4614         _e_border_action_restore_orig(action_border);
4615         goto stop;
4616      }
4617    else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
4618             (strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
4619      goto stop;
4620
4621    e_border_move(action_border, x, y);
4622    _e_border_action_move_timeout_add();
4623
4624    return ECORE_CALLBACK_PASS_ON;
4625
4626 stop:
4627    _e_border_move_end(action_border);
4628    _e_border_action_finish();
4629    return ECORE_CALLBACK_DONE;
4630 }
4631
4632 static Eina_Bool
4633 _e_border_move_mouse_down(void *data __UNUSED__,
4634                           int type   __UNUSED__,
4635                           void      *event)
4636 {
4637    Ecore_Event_Mouse_Button *ev = event;
4638
4639    if (ev->event_window != action_input_win)
4640      return ECORE_CALLBACK_PASS_ON;
4641
4642    if (!action_border)
4643      fputs("ERROR: no action_border!\n", stderr);
4644
4645    _e_border_move_end(action_border);
4646    _e_border_action_finish();
4647    return ECORE_CALLBACK_DONE;
4648 }
4649
4650 EAPI void
4651 e_border_act_move_keyboard(E_Border *bd)
4652 {
4653    if (!bd)
4654      return;
4655
4656    if (!_e_border_move_begin(bd))
4657      return;
4658
4659    if (!_e_border_action_input_win_new(bd))
4660      {
4661         _e_border_move_end(bd);
4662         return;
4663      }
4664
4665    _e_border_action_init(bd);
4666    _e_border_action_move_timeout_add();
4667    _e_border_move_update(bd);
4668
4669    if (action_handler_key)
4670      ecore_event_handler_del(action_handler_key);
4671    action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_move_key_down, NULL);
4672
4673    if (action_handler_mouse)
4674      ecore_event_handler_del(action_handler_mouse);
4675    action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_move_mouse_down, NULL);
4676 }
4677
4678 static Eina_Bool
4679 _e_border_action_resize_timeout(void *data __UNUSED__)
4680 {
4681    _e_border_resize_end(action_border);
4682    _e_border_action_finish();
4683    return ECORE_CALLBACK_CANCEL;
4684 }
4685
4686 static void
4687 _e_border_action_resize_timeout_add(void)
4688 {
4689    if (action_timer)
4690      ecore_timer_del(action_timer);
4691    action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_resize_timeout, NULL);
4692 }
4693
4694 static Eina_Bool
4695 _e_border_resize_key_down(void *data __UNUSED__,
4696                           int type   __UNUSED__,
4697                           void      *event)
4698 {
4699    Ecore_Event_Key *ev = event;
4700    int w, h, dx, dy;
4701
4702    if (ev->event_window != action_input_win)
4703      return ECORE_CALLBACK_PASS_ON;
4704    if (!action_border)
4705      {
4706         fputs("ERROR: no action_border!\n", stderr);
4707         goto stop;
4708      }
4709
4710    w = action_border->w;
4711    h = action_border->h;
4712
4713    dx = e_config->border_keyboard.resize.dx;
4714    if (dx < action_border->client.icccm.step_w)
4715      dx = action_border->client.icccm.step_w;
4716    dx = _e_border_key_down_modifier_apply(ev->modifiers, dx);
4717    if (dx < action_border->client.icccm.step_w)
4718      dx = action_border->client.icccm.step_w;
4719
4720    dy = e_config->border_keyboard.resize.dy;
4721    if (dy < action_border->client.icccm.step_h)
4722      dy = action_border->client.icccm.step_h;
4723    dy = _e_border_key_down_modifier_apply(ev->modifiers, dy);
4724    if (dy < action_border->client.icccm.step_h)
4725      dy = action_border->client.icccm.step_h;
4726
4727    if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
4728      h -= dy;
4729    else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
4730      h += dy;
4731    else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
4732      w -= dx;
4733    else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
4734      w += dx;
4735    else if (strcmp(ev->key, "Return") == 0)
4736      goto stop;
4737    else if (strcmp(ev->key, "Escape") == 0)
4738      {
4739         _e_border_action_restore_orig(action_border);
4740         goto stop;
4741      }
4742    else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
4743             (strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
4744      goto stop;
4745
4746    e_border_resize_limit(action_border, &w, &h);
4747    e_border_resize(action_border, w, h);
4748    _e_border_action_resize_timeout_add();
4749
4750    return ECORE_CALLBACK_PASS_ON;
4751
4752 stop:
4753    _e_border_resize_end(action_border);
4754    _e_border_action_finish();
4755    return ECORE_CALLBACK_DONE;
4756 }
4757
4758 static Eina_Bool
4759 _e_border_resize_mouse_down(void *data __UNUSED__,
4760                             int type   __UNUSED__,
4761                             void      *event)
4762 {
4763    Ecore_Event_Mouse_Button *ev = event;
4764
4765    if (ev->event_window != action_input_win)
4766      return ECORE_CALLBACK_PASS_ON;
4767
4768    if (!action_border)
4769      fputs("ERROR: no action_border!\n", stderr);
4770
4771    _e_border_resize_end(action_border);
4772    _e_border_action_finish();
4773    return ECORE_CALLBACK_DONE;
4774 }
4775
4776 EAPI void
4777 e_border_act_resize_keyboard(E_Border *bd)
4778 {
4779    if (!bd)
4780      return;
4781
4782    if (!_e_border_resize_begin(bd))
4783      return;
4784
4785    if (!_e_border_action_input_win_new(bd))
4786      {
4787         _e_border_resize_end(bd);
4788         return;
4789      }
4790
4791    _e_border_action_init(bd);
4792    _e_border_action_resize_timeout_add();
4793    _e_border_resize_update(bd);
4794
4795    if (action_handler_key)
4796      ecore_event_handler_del(action_handler_key);
4797    action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_resize_key_down, NULL);
4798
4799    if (action_handler_mouse)
4800      ecore_event_handler_del(action_handler_mouse);
4801    action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_resize_mouse_down, NULL);
4802 }
4803
4804 EAPI void
4805 e_border_act_move_begin(E_Border                 *bd,
4806                         Ecore_Event_Mouse_Button *ev)
4807 {
4808    E_OBJECT_CHECK(bd);
4809    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4810    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
4811    if (!_e_border_move_begin(bd))
4812      return;
4813
4814    e_zone_edge_disable();
4815    bd->moving = 1;
4816    _e_border_pointer_move_begin(bd);
4817    if (ev)
4818      {
4819         char source[256];
4820
4821         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->buttons);
4822         _e_border_moveinfo_gather(bd, source);
4823      }
4824 }
4825
4826 EAPI void
4827 e_border_act_move_end(E_Border                    *bd,
4828                       Ecore_Event_Mouse_Button *ev __UNUSED__)
4829 {
4830    E_OBJECT_CHECK(bd);
4831    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4832    if (!bd->moving) return;
4833    bd->moving = 0;
4834    _e_border_pointer_move_end(bd);
4835    e_zone_edge_enable();
4836    _e_border_move_end(bd);
4837    e_zone_flip_coords_handle(bd->zone, -1, -1);
4838 }
4839
4840 EAPI void
4841 e_border_act_resize_begin(E_Border                 *bd,
4842                           Ecore_Event_Mouse_Button *ev)
4843 {
4844    E_OBJECT_CHECK(bd);
4845    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4846    if (bd->lock_user_size) return;
4847    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
4848    if (!_e_border_resize_begin(bd))
4849      return;
4850    if (bd->mouse.current.mx < (bd->x + bd->w / 2))
4851      {
4852         if (bd->mouse.current.my < (bd->y + bd->h / 2))
4853           {
4854              bd->resize_mode = RESIZE_TL;
4855              GRAV_SET(bd, ECORE_X_GRAVITY_SE);
4856           }
4857         else
4858           {
4859              bd->resize_mode = RESIZE_BL;
4860              GRAV_SET(bd, ECORE_X_GRAVITY_NE);
4861           }
4862      }
4863    else
4864      {
4865         if (bd->mouse.current.my < (bd->y + bd->h / 2))
4866           {
4867              bd->resize_mode = RESIZE_TR;
4868              GRAV_SET(bd, ECORE_X_GRAVITY_SW);
4869           }
4870         else
4871           {
4872              bd->resize_mode = RESIZE_BR;
4873              GRAV_SET(bd, ECORE_X_GRAVITY_NW);
4874           }
4875      }
4876    _e_border_pointer_resize_begin(bd);
4877    if (ev)
4878      {
4879         char source[256];
4880
4881         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->buttons);
4882         _e_border_moveinfo_gather(bd, source);
4883      }
4884 }
4885
4886 EAPI void
4887 e_border_act_resize_end(E_Border                    *bd,
4888                         Ecore_Event_Mouse_Button *ev __UNUSED__)
4889 {
4890    E_OBJECT_CHECK(bd);
4891    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4892    if (bd->resize_mode != RESIZE_NONE)
4893      {
4894         _e_border_pointer_resize_end(bd);
4895         bd->resize_mode = RESIZE_NONE;
4896         _e_border_resize_end(bd);
4897         bd->changes.reset_gravity = 1;
4898         bd->changed = 1;
4899      }
4900 }
4901
4902 EAPI void
4903 e_border_act_menu_begin(E_Border                 *bd,
4904                         Ecore_Event_Mouse_Button *ev,
4905                         int                       key)
4906 {
4907    E_OBJECT_CHECK(bd);
4908    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4909    if (ev)
4910      {
4911         e_int_border_menu_show(bd,
4912                                bd->x + bd->fx.x + ev->x - bd->zone->container->x,
4913                                bd->y + bd->fx.y + ev->y - bd->zone->container->y, key,
4914                                ev->timestamp);
4915      }
4916    else
4917      {
4918         int x, y;
4919
4920         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
4921         e_int_border_menu_show(bd, x, y, key, 0);
4922      }
4923 }
4924
4925 EAPI void
4926 e_border_act_close_begin(E_Border *bd)
4927 {
4928    E_OBJECT_CHECK(bd);
4929    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4930    if (bd->lock_close) return;
4931    if (bd->client.icccm.delete_request)
4932      {
4933         bd->delete_requested = 1;
4934         ecore_x_window_delete_request_send(bd->client.win);
4935         if (bd->client.netwm.ping)
4936           e_border_ping(bd);
4937      }
4938    else if (e_config->kill_if_close_not_possible)
4939      {
4940         e_border_act_kill_begin(bd);
4941      }
4942 }
4943
4944 EAPI void
4945 e_border_act_kill_begin(E_Border *bd)
4946 {
4947    E_OBJECT_CHECK(bd);
4948    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4949    if (bd->internal) return;
4950    if (bd->lock_close) return;
4951    if ((bd->client.netwm.pid > 1) && (e_config->kill_process))
4952      {
4953         kill(bd->client.netwm.pid, SIGINT);
4954         bd->kill_timer = ecore_timer_add(e_config->kill_timer_wait,
4955                                          _e_border_cb_kill_timer, bd);
4956      }
4957    else
4958      {
4959         if (!bd->internal) ecore_x_kill(bd->client.win);
4960      }
4961 }
4962
4963 EAPI Evas_Object *
4964 e_border_icon_add(E_Border *bd,
4965                   Evas     *evas)
4966 {
4967    Evas_Object *o;
4968
4969    E_OBJECT_CHECK_RETURN(bd, NULL);
4970    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, NULL);
4971
4972    o = NULL;
4973    if (bd->internal)
4974      {
4975         if (!bd->internal_icon)
4976           {
4977              o = e_icon_add(evas);
4978              e_util_icon_theme_set(o, "enlightenment");
4979           }
4980         else
4981           {
4982              if (!bd->internal_icon_key)
4983                {
4984                   char *ext;
4985
4986                   ext = strrchr(bd->internal_icon, '.');
4987                   if ((ext) && ((!strcmp(ext, ".edj"))))
4988                     {
4989                        o = edje_object_add(evas);
4990                        if (!edje_object_file_set(o, bd->internal_icon, "icon"))
4991                          e_util_icon_theme_set(o, "enlightenment");
4992                     }
4993                   else if (ext)
4994                     {
4995                        o = e_icon_add(evas);
4996                        e_icon_file_set(o, bd->internal_icon);
4997                     }
4998                   else
4999                     {
5000                        o = e_icon_add(evas);
5001                        if (!e_util_icon_theme_set(o, bd->internal_icon))
5002                          e_util_icon_theme_set(o, "enlightenment");
5003                     }
5004                }
5005              else
5006                {
5007                   o = edje_object_add(evas);
5008                   edje_object_file_set(o, bd->internal_icon,
5009                                        bd->internal_icon_key);
5010                }
5011           }
5012         return o;
5013      }
5014    if ((e_config->use_app_icon) && (bd->icon_preference != E_ICON_PREF_USER))
5015      {
5016         if (bd->client.netwm.icons)
5017           {
5018              o = e_icon_add(evas);
5019              e_icon_data_set(o, bd->client.netwm.icons[0].data,
5020                              bd->client.netwm.icons[0].width,
5021                              bd->client.netwm.icons[0].height);
5022              e_icon_alpha_set(o, 1);
5023              return o;
5024           }
5025      }
5026    if (!o)
5027      {
5028         if ((bd->desktop) && (bd->icon_preference != E_ICON_PREF_NETWM))
5029           {
5030              o = e_icon_add(evas);
5031              if (o)
5032                {
5033                   e_icon_fdo_icon_set(o, bd->desktop->icon);
5034                   return o;
5035                }
5036           }
5037         else if (bd->client.netwm.icons)
5038           {
5039              o = e_icon_add(evas);
5040              e_icon_data_set(o, bd->client.netwm.icons[0].data,
5041                              bd->client.netwm.icons[0].width,
5042                              bd->client.netwm.icons[0].height);
5043              e_icon_alpha_set(o, 1);
5044              return o;
5045           }
5046      }
5047
5048    o = e_icon_add(evas);
5049    e_util_icon_theme_set(o, "unknown");
5050    return o;
5051 }
5052
5053 EAPI void
5054 e_border_button_bindings_ungrab_all(void)
5055 {
5056    Eina_List *l;
5057    E_Border *bd;
5058
5059    EINA_LIST_FOREACH(borders, l, bd)
5060      {
5061         e_focus_setdown(bd);
5062         e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5063         e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5064      }
5065 }
5066
5067 EAPI void
5068 e_border_button_bindings_grab_all(void)
5069 {
5070    Eina_List *l;
5071    E_Border *bd;
5072
5073    EINA_LIST_FOREACH(borders, l, bd)
5074      {
5075         e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
5076         e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
5077         e_focus_setup(bd);
5078      }
5079 }
5080
5081 EAPI Eina_List *
5082 e_border_focus_stack_get(void)
5083 {
5084    return focus_stack;
5085 }
5086
5087 EAPI Eina_List *
5088 e_border_raise_stack_get(void)
5089 {
5090    return raise_stack;
5091 }
5092
5093 EAPI Eina_List *
5094 e_border_lost_windows_get(E_Zone *zone)
5095 {
5096    Eina_List *list = NULL, *l;
5097    E_Border *bd;
5098    int loss_overlap = 5;
5099
5100    E_OBJECT_CHECK_RETURN(zone, NULL);
5101    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
5102    EINA_LIST_FOREACH(borders, l, bd)
5103      {
5104         if (!bd->zone)
5105           continue;
5106
5107         if ((bd->zone != zone) ||
5108             (bd->zone->container != zone->container))
5109           continue;
5110
5111         if (!E_INTERSECTS(bd->zone->x + loss_overlap,
5112                           bd->zone->y + loss_overlap,
5113                           bd->zone->w - (2 * loss_overlap),
5114                           bd->zone->h - (2 * loss_overlap),
5115                           bd->x, bd->y, bd->w, bd->h))
5116           {
5117              list = eina_list_append(list, bd);
5118           }
5119         else if ((!E_CONTAINS(bd->zone->x, bd->zone->y,
5120                               bd->zone->w, bd->zone->h,
5121                               bd->x, bd->y, bd->w, bd->h)) &&
5122                  (bd->shaped))
5123           {
5124              Ecore_X_Rectangle *rect;
5125              int i, num;
5126
5127              rect = ecore_x_window_shape_rectangles_get(bd->win, &num);
5128              if (rect)
5129                {
5130                   int ok;
5131
5132                   ok = 0;
5133                   for (i = 0; i < num; i++)
5134                     {
5135                        if (E_INTERSECTS(bd->zone->x + loss_overlap,
5136                                         bd->zone->y + loss_overlap,
5137                                         bd->zone->w - (2 * loss_overlap),
5138                                         bd->zone->h - (2 * loss_overlap),
5139                                         rect[i].x, rect[i].y,
5140                                         (int)rect[i].width, (int)rect[i].height))
5141                          {
5142                             ok = 1;
5143                             break;
5144                          }
5145                     }
5146                   free(rect);
5147                   if (!ok)
5148                     list = eina_list_append(list, bd);
5149                }
5150           }
5151      }
5152    return list;
5153 }
5154
5155 EAPI void
5156 e_border_ping(E_Border *bd)
5157 {
5158    E_OBJECT_CHECK(bd);
5159    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5160    if (!e_config->ping_clients) return;
5161    bd->ping_ok = 0;
5162    ecore_x_netwm_ping_send(bd->client.win);
5163    bd->ping = ecore_loop_time_get();
5164    if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
5165    bd->ping_poller = ecore_poller_add(ECORE_POLLER_CORE,
5166                                       e_config->ping_clients_interval,
5167                                       _e_border_cb_ping_poller, bd);
5168 }
5169
5170 EAPI void
5171 e_border_move_cancel(void)
5172 {
5173    if (bdmove)
5174      {
5175         if (bdmove->cur_mouse_action)
5176           {
5177              E_Border *bd;
5178
5179              bd = bdmove;
5180              e_object_ref(E_OBJECT(bd));
5181              if (bd->cur_mouse_action->func.end_mouse)
5182                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
5183              else if (bd->cur_mouse_action->func.end)
5184                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
5185              e_object_unref(E_OBJECT(bd->cur_mouse_action));
5186              bd->cur_mouse_action = NULL;
5187              e_object_unref(E_OBJECT(bd));
5188           }
5189         else
5190           _e_border_move_end(bdmove);
5191      }
5192 }
5193
5194 EAPI void
5195 e_border_resize_cancel(void)
5196 {
5197    if (bdresize)
5198      {
5199         if (bdresize->cur_mouse_action)
5200           {
5201              E_Border *bd;
5202
5203              bd = bdresize;
5204              e_object_ref(E_OBJECT(bd));
5205              if (bd->cur_mouse_action->func.end_mouse)
5206                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
5207              else if (bd->cur_mouse_action->func.end)
5208                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
5209              e_object_unref(E_OBJECT(bd->cur_mouse_action));
5210              bd->cur_mouse_action = NULL;
5211              e_object_unref(E_OBJECT(bd));
5212           }
5213         else
5214           {
5215              bdresize->resize_mode = RESIZE_NONE;
5216              _e_border_resize_end(bdresize);
5217           }
5218      }
5219 }
5220
5221 EAPI void
5222 e_border_frame_recalc(E_Border *bd)
5223 {
5224    if (!bd->bg_object) return;
5225
5226    bd->w -= (bd->client_inset.l + bd->client_inset.r);
5227    bd->h -= (bd->client_inset.t + bd->client_inset.b);
5228
5229    _e_border_client_inset_calc(bd);
5230
5231    bd->w += (bd->client_inset.l + bd->client_inset.r);
5232    bd->h += (bd->client_inset.t + bd->client_inset.b);
5233
5234    bd->changed = 1;
5235    bd->changes.size = 1;
5236    if ((bd->shaped) || (bd->client.shaped))
5237      {
5238         bd->need_shape_merge = 1;
5239         bd->need_shape_export = 1;
5240      }
5241    if (bd->shaped_input)
5242      {
5243         bd->need_shape_merge = 1;
5244      }
5245    _e_border_client_move_resize_send(bd);
5246 }
5247
5248 EAPI Eina_List *
5249 e_border_immortal_windows_get(void)
5250 {
5251    Eina_List *list = NULL, *l;
5252    E_Border *bd;
5253
5254    EINA_LIST_FOREACH(borders, l, bd)
5255      {
5256         if (bd->lock_life)
5257           list = eina_list_append(list, bd);
5258      }
5259    return list;
5260 }
5261
5262 EAPI const char *
5263 e_border_name_get(const E_Border *bd)
5264 {
5265    E_OBJECT_CHECK_RETURN(bd, "");
5266    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, "");
5267    if (bd->client.netwm.name)
5268      return bd->client.netwm.name;
5269    else if (bd->client.icccm.title)
5270      return bd->client.icccm.title;
5271    return "";
5272 }
5273
5274 EAPI void
5275 e_border_signal_move_begin(E_Border       *bd,
5276                            const char     *sig,
5277                            const char *src __UNUSED__)
5278 {
5279    E_OBJECT_CHECK(bd);
5280    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5281
5282    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
5283    if (!_e_border_move_begin(bd)) return;
5284    bd->moving = 1;
5285    _e_border_pointer_move_begin(bd);
5286    e_zone_edge_disable();
5287    _e_border_moveinfo_gather(bd, sig);
5288    if (bd->cur_mouse_action)
5289      {
5290         if ((!bd->cur_mouse_action->func.end_mouse) &&
5291             (!bd->cur_mouse_action->func.end))
5292           bd->cur_mouse_action = NULL;
5293         else
5294           e_object_unref(E_OBJECT(bd->cur_mouse_action));
5295      }
5296    bd->cur_mouse_action = e_action_find("window_move");
5297    if (bd->cur_mouse_action)
5298      e_object_ref(E_OBJECT(bd->cur_mouse_action));
5299 }
5300
5301 EAPI void
5302 e_border_signal_move_end(E_Border       *bd,
5303                          const char *sig __UNUSED__,
5304                          const char *src __UNUSED__)
5305 {
5306    E_OBJECT_CHECK(bd);
5307    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5308    if (!bd->moving) return;
5309    bd->moving = 0;
5310    _e_border_pointer_move_end(bd);
5311    e_zone_edge_enable();
5312    _e_border_move_end(bd);
5313    e_zone_flip_coords_handle(bd->zone, -1, -1);
5314 }
5315
5316 EAPI int
5317 e_border_resizing_get(E_Border *bd)
5318 {
5319    E_OBJECT_CHECK_RETURN(bd, 0);
5320    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, 0);
5321    if (bd->resize_mode == RESIZE_NONE) return 0;
5322    return 1;
5323 }
5324
5325 EAPI void
5326 e_border_signal_resize_begin(E_Border       *bd,
5327                              const char     *dir,
5328                              const char     *sig,
5329                              const char *src __UNUSED__)
5330 {
5331    Ecore_X_Gravity grav = ECORE_X_GRAVITY_NW;
5332    int resize_mode = RESIZE_BR;
5333
5334    E_OBJECT_CHECK(bd);
5335    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5336
5337    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
5338    if (!_e_border_resize_begin(bd))
5339      return;
5340    if (!strcmp(dir, "tl"))
5341      {
5342         resize_mode = RESIZE_TL;
5343         grav = ECORE_X_GRAVITY_SE;
5344      }
5345    else if (!strcmp(dir, "t"))
5346      {
5347         resize_mode = RESIZE_T;
5348         grav = ECORE_X_GRAVITY_S;
5349      }
5350    else if (!strcmp(dir, "tr"))
5351      {
5352         resize_mode = RESIZE_TR;
5353         grav = ECORE_X_GRAVITY_SW;
5354      }
5355    else if (!strcmp(dir, "r"))
5356      {
5357         resize_mode = RESIZE_R;
5358         grav = ECORE_X_GRAVITY_W;
5359      }
5360    else if (!strcmp(dir, "br"))
5361      {
5362         resize_mode = RESIZE_BR;
5363         grav = ECORE_X_GRAVITY_NW;
5364      }
5365    else if (!strcmp(dir, "b"))
5366      {
5367         resize_mode = RESIZE_B;
5368         grav = ECORE_X_GRAVITY_N;
5369      }
5370    else if (!strcmp(dir, "bl"))
5371      {
5372         resize_mode = RESIZE_BL;
5373         grav = ECORE_X_GRAVITY_NE;
5374      }
5375    else if (!strcmp(dir, "l"))
5376      {
5377         resize_mode = RESIZE_L;
5378         grav = ECORE_X_GRAVITY_E;
5379      }
5380    bd->resize_mode = resize_mode;
5381    _e_border_pointer_resize_begin(bd);
5382    _e_border_moveinfo_gather(bd, sig);
5383    GRAV_SET(bd, grav);
5384    if (bd->cur_mouse_action)
5385      {
5386         if ((!bd->cur_mouse_action->func.end_mouse) &&
5387             (!bd->cur_mouse_action->func.end))
5388           bd->cur_mouse_action = NULL;
5389         else
5390           e_object_unref(E_OBJECT(bd->cur_mouse_action));
5391      }
5392    bd->cur_mouse_action = e_action_find("window_resize");
5393    if (bd->cur_mouse_action)
5394      e_object_ref(E_OBJECT(bd->cur_mouse_action));
5395 }
5396
5397 EAPI void
5398 e_border_signal_resize_end(E_Border       *bd,
5399                            const char *dir __UNUSED__,
5400                            const char *sig __UNUSED__,
5401                            const char *src __UNUSED__)
5402 {
5403    E_OBJECT_CHECK(bd);
5404    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5405    if (bd->resize_mode == RESIZE_NONE) return;
5406    _e_border_resize_handle(bd);
5407    _e_border_pointer_resize_end(bd);
5408    bd->resize_mode = RESIZE_NONE;
5409    _e_border_resize_end(bd);
5410    bd->changes.reset_gravity = 1;
5411    bd->changed = 1;
5412 }
5413
5414 EAPI void
5415 e_border_resize_limit(E_Border *bd,
5416                       int      *w,
5417                       int      *h)
5418 {
5419    double a;
5420
5421    E_OBJECT_CHECK(bd);
5422    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5423    *w -= bd->client_inset.l + bd->client_inset.r;
5424    *h -= bd->client_inset.t + bd->client_inset.b;
5425    if (*h < 1) *h = 1;
5426    if (*w < 1) *w = 1;
5427    if ((bd->client.icccm.base_w >= 0) &&
5428        (bd->client.icccm.base_h >= 0))
5429      {
5430         int tw, th;
5431
5432         tw = *w - bd->client.icccm.base_w;
5433         th = *h - bd->client.icccm.base_h;
5434         if (tw < 1) tw = 1;
5435         if (th < 1) th = 1;
5436         a = (double)(tw) / (double)(th);
5437         if ((bd->client.icccm.min_aspect != 0.0) &&
5438             (a < bd->client.icccm.min_aspect))
5439           {
5440              th = tw / bd->client.icccm.max_aspect;
5441              *h = th + bd->client.icccm.base_h;
5442           }
5443         else if ((bd->client.icccm.max_aspect != 0.0) &&
5444                  (a > bd->client.icccm.max_aspect))
5445           {
5446              tw = th * bd->client.icccm.max_aspect;
5447              *w = tw + bd->client.icccm.base_w;
5448           }
5449      }
5450    else
5451      {
5452         a = (double)*w / (double)*h;
5453         if ((bd->client.icccm.min_aspect != 0.0) &&
5454             (a < bd->client.icccm.min_aspect))
5455           *h = *w / bd->client.icccm.min_aspect;
5456         else if ((bd->client.icccm.max_aspect != 0.0) &&
5457                  (a > bd->client.icccm.max_aspect))
5458           *w = *h * bd->client.icccm.max_aspect;
5459      }
5460    if (bd->client.icccm.step_w > 0)
5461      {
5462         if (bd->client.icccm.base_w >= 0)
5463           *w = bd->client.icccm.base_w +
5464             (((*w - bd->client.icccm.base_w) / bd->client.icccm.step_w) *
5465              bd->client.icccm.step_w);
5466         else
5467           *w = bd->client.icccm.min_w +
5468             (((*w - bd->client.icccm.min_w) / bd->client.icccm.step_w) *
5469              bd->client.icccm.step_w);
5470      }
5471    if (bd->client.icccm.step_h > 0)
5472      {
5473         if (bd->client.icccm.base_h >= 0)
5474           *h = bd->client.icccm.base_h +
5475             (((*h - bd->client.icccm.base_h) / bd->client.icccm.step_h) *
5476              bd->client.icccm.step_h);
5477         else
5478           *h = bd->client.icccm.min_h +
5479             (((*h - bd->client.icccm.min_h) / bd->client.icccm.step_h) *
5480              bd->client.icccm.step_h);
5481      }
5482
5483    if (*h < 1) *h = 1;
5484    if (*w < 1) *w = 1;
5485
5486    if      (*w > bd->client.icccm.max_w) *w = bd->client.icccm.max_w;
5487    else if (*w < bd->client.icccm.min_w)
5488      *w = bd->client.icccm.min_w;
5489    if      (*h > bd->client.icccm.max_h) *h = bd->client.icccm.max_h;
5490    else if (*h < bd->client.icccm.min_h)
5491      *h = bd->client.icccm.min_h;
5492
5493    *w += bd->client_inset.l + bd->client_inset.r;
5494    *h += bd->client_inset.t + bd->client_inset.b;
5495 }
5496
5497 /* local subsystem functions */
5498 static void
5499 _e_border_free(E_Border *bd)
5500 {
5501 #ifdef _F_USE_DESK_WINDOW_PROFILE_
5502    const char *str;
5503 #endif
5504    if (bd->client.e.state.video_parent && bd->client.e.state.video_parent_border)
5505      {
5506         bd->client.e.state.video_parent_border->client.e.state.video_child =
5507           eina_list_remove
5508           (bd->client.e.state.video_parent_border->client.e.state.video_child,
5509               bd);
5510      }
5511    if (bd->client.e.state.video_child)
5512      {
5513         E_Border *tmp;
5514
5515         EINA_LIST_FREE(bd->client.e.state.video_child, tmp)
5516           {
5517              tmp->client.e.state.video_parent_border = NULL;
5518           }
5519      }
5520    if (bd->desktop)
5521      {
5522         efreet_desktop_free(bd->desktop);
5523         bd->desktop = NULL;
5524      }
5525    if (bd->post_job)
5526      {
5527         ecore_idle_enterer_del(bd->post_job);
5528         bd->post_job = NULL;
5529      }
5530    if (bd->pointer)
5531      {
5532         e_object_del(E_OBJECT(bd->pointer));
5533         bd->pointer = NULL;
5534      }
5535    if (bdresize == bd)
5536      _e_border_resize_end(bd);
5537    if (bdmove == bd)
5538      _e_border_move_end(bd);
5539    /* TODO: Other states to end before dying? */
5540
5541    if (bd->cur_mouse_action)
5542      {
5543         e_object_unref(E_OBJECT(bd->cur_mouse_action));
5544         bd->cur_mouse_action = NULL;
5545      }
5546
5547    E_FREE(bd->shape_rects);
5548    bd->shape_rects_num = 0;
5549 /*
5550    if (bd->dangling_ref_check)
5551      {
5552         ecore_timer_del(bd->dangling_ref_check);
5553         bd->dangling_ref_check = NULL;
5554      }
5555  */
5556    if (bd->kill_timer)
5557      {
5558         ecore_timer_del(bd->kill_timer);
5559         bd->kill_timer = NULL;
5560      }
5561    if (bd->ping_poller)
5562      {
5563         ecore_poller_del(bd->ping_poller);
5564         bd->ping_poller = NULL;
5565      }
5566    E_FREE_LIST(bd->pending_move_resize, free);
5567
5568    if (bd->shade.anim) ecore_animator_del(bd->shade.anim);
5569    if (bd->border_menu) e_menu_deactivate(bd->border_menu);
5570
5571    if (bd->border_locks_dialog)
5572      {
5573         e_object_del(E_OBJECT(bd->border_locks_dialog));
5574         bd->border_locks_dialog = NULL;
5575      }
5576    if (bd->border_remember_dialog)
5577      {
5578         e_object_del(E_OBJECT(bd->border_remember_dialog));
5579         bd->border_remember_dialog = NULL;
5580      }
5581    if (bd->border_border_dialog)
5582      {
5583         e_object_del(E_OBJECT(bd->border_border_dialog));
5584         bd->border_border_dialog = NULL;
5585      }
5586    if (bd->border_prop_dialog)
5587      {
5588         e_object_del(E_OBJECT(bd->border_prop_dialog));
5589         bd->border_prop_dialog = NULL;
5590      }
5591
5592    e_int_border_menu_del(bd);
5593
5594    if (focusing == bd)
5595      focusing = NULL;
5596
5597    focus_next = eina_list_remove(focus_next, bd);
5598    
5599    if ((focused == bd) ||
5600        (e_grabinput_last_focus_win_get() == bd->client.win))
5601      {
5602         if ((!focus_next) && (!focusing))
5603           {
5604              e_grabinput_focus(bd->zone->container->bg_win,
5605                                E_FOCUS_METHOD_PASSIVE);
5606              e_hints_active_window_set(bd->zone->container->manager, NULL);
5607           }
5608
5609         focused = NULL;
5610      }
5611    E_FREE_LIST(bd->handlers, ecore_event_handler_del);
5612    if (bd->remember)
5613      {
5614         E_Remember *rem;
5615
5616         rem = bd->remember;
5617         bd->remember = NULL;
5618         e_remember_unuse(rem);
5619      }
5620    if (!bd->already_unparented)
5621      {
5622         ecore_x_window_reparent(bd->client.win, bd->zone->container->manager->root,
5623                                 bd->x + bd->client_inset.l, bd->y + bd->client_inset.t);
5624         ecore_x_window_save_set_del(bd->client.win);
5625         bd->already_unparented = 1;
5626      }
5627    if (bd->group) eina_list_free(bd->group);
5628    if (bd->transients) eina_list_free(bd->transients);
5629    if (bd->stick_desks) eina_list_free(bd->stick_desks);
5630    if (bd->client.netwm.icons)
5631      {
5632         int i;
5633         for (i = 0; i < bd->client.netwm.num_icons; i++)
5634           free(bd->client.netwm.icons[i].data);
5635         free(bd->client.netwm.icons);
5636      }
5637    if (bd->client.netwm.extra_types)
5638      free(bd->client.netwm.extra_types);
5639    if (bd->client.border.name)
5640      eina_stringshare_del(bd->client.border.name);
5641    if (bd->bordername)
5642      eina_stringshare_del(bd->bordername);
5643    if (bd->client.icccm.name)
5644      eina_stringshare_del(bd->client.icccm.name);
5645    if (bd->client.icccm.class)
5646      {
5647         if (!strcmp(bd->client.icccm.class, "Vmplayer"))
5648           e_bindings_mapping_change_enable(EINA_TRUE);
5649         eina_stringshare_del(bd->client.icccm.class);
5650      }
5651    if (bd->client.icccm.title)
5652      eina_stringshare_del(bd->client.icccm.title);
5653    if (bd->client.icccm.icon_name)
5654      eina_stringshare_del(bd->client.icccm.icon_name);
5655    if (bd->client.icccm.machine)
5656      eina_stringshare_del(bd->client.icccm.machine);
5657    if (bd->client.icccm.window_role)
5658      eina_stringshare_del(bd->client.icccm.window_role);
5659
5660    if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
5661      {
5662         int i;
5663
5664         for (i = 0; i < bd->client.icccm.command.argc; i++)
5665           free(bd->client.icccm.command.argv[i]);
5666         free(bd->client.icccm.command.argv);
5667      }
5668    if (bd->client.netwm.name)
5669      eina_stringshare_del(bd->client.netwm.name);
5670    if (bd->client.netwm.icon_name)
5671      eina_stringshare_del(bd->client.netwm.icon_name);
5672    e_object_del(E_OBJECT(bd->shape));
5673    if (bd->internal_icon) eina_stringshare_del(bd->internal_icon);
5674    if (bd->internal_icon_key) eina_stringshare_del(bd->internal_icon_key);
5675    if (bd->icon_object) evas_object_del(bd->icon_object);
5676 #ifdef _F_USE_DESK_WINDOW_PROFILE_
5677    EINA_LIST_FREE(bd->client.e.state.profiles, str)
5678      {
5679         if (str) eina_stringshare_del(str);
5680      }
5681    bd->client.e.state.profiles = NULL;
5682    if (bd->client.e.state.profile)
5683      eina_stringshare_del(bd->client.e.state.profile);
5684    bd->client.e.state.profile = NULL;
5685 #endif
5686 #ifdef _F_ZONE_WINDOW_ROTATION_
5687    if (e_config->wm_win_rotation)
5688      {
5689         bd->client.e.fetch.rot.app_set = 0;
5690         bd->client.e.state.rot.preferred_rot = -1;
5691
5692         if (bd->client.e.state.rot.available_rots)
5693           E_FREE(bd->client.e.state.rot.available_rots);
5694
5695         _e_border_rotation_list_remove(bd);
5696         if ((rot.vkbd) && (rot.vkbd == bd))
5697           {
5698              ELB(ELBT_BD, "UNSET VKBD", bd->client.win);
5699              rot.vkbd = NULL;
5700              if (rot.vkbd_ctrl_win)
5701                {
5702                   ELB(ELBT_BD, "SET KBD_OFF", 0);
5703                   ecore_x_e_virtual_keyboard_state_set
5704                     (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
5705                }
5706
5707              rot.vkbd_hide_prepare_done = EINA_FALSE;
5708              if (rot.vkbd_hide_prepare_timer)
5709                ecore_timer_del(rot.vkbd_hide_prepare_timer);
5710              rot.vkbd_hide_prepare_timer = NULL;
5711              if (rot.vkbd_hide_timer)
5712                ecore_timer_del(rot.vkbd_hide_timer);
5713              rot.vkbd_hide_timer = NULL;
5714
5715              rot.vkbd_show_prepare_done = EINA_FALSE;
5716              if (rot.vkbd_show_prepare_timer)
5717                ecore_timer_del(rot.vkbd_show_prepare_timer);
5718              rot.vkbd_show_prepare_timer = NULL;
5719              if (rot.vkbd_show_timer)
5720                ecore_timer_del(rot.vkbd_show_timer);
5721              rot.vkbd_show_timer = NULL;
5722           }
5723         else if ((rot.vkbd_prediction) &&
5724                  (rot.vkbd_prediction == bd))
5725           rot.vkbd_prediction = NULL;
5726      }
5727 #endif
5728 #ifdef _F_DEICONIFY_APPROVE_
5729    if (bd->client.e.state.deiconify_approve.pending_job)
5730      {
5731         ecore_job_del(bd->client.e.state.deiconify_approve.pending_job);
5732         bd->client.e.state.deiconify_approve.pending_job = NULL;
5733      }
5734 #endif
5735    evas_object_del(bd->bg_object);
5736    e_canvas_del(bd->bg_ecore_evas);
5737    ecore_evas_free(bd->bg_ecore_evas);
5738    ecore_x_window_free(bd->client.shell_win);
5739    e_focus_setdown(bd);
5740    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5741    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5742    ecore_x_window_free(bd->win);
5743
5744    eina_hash_del(borders_hash, e_util_winid_str_get(bd->client.win), bd);
5745    eina_hash_del(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
5746    eina_hash_del(borders_hash, e_util_winid_str_get(bd->win), bd);
5747    borders = eina_list_remove(borders, bd);
5748    focus_stack = eina_list_remove(focus_stack, bd);
5749    raise_stack = eina_list_remove(raise_stack, bd);
5750
5751    e_container_border_remove(bd);
5752    free(bd);
5753 }
5754
5755 /*
5756    static int
5757    _e_border_del_dangling_ref_check(void *data)
5758    {
5759    E_Border *bd;
5760
5761    bd = data;
5762    printf("---\n");
5763    printf("EEK EEK border still around 1 second after being deleted!\n");
5764    printf("%p, %i, \"%s\" [\"%s\" \"%s\"]\n",
5765           bd, e_object_ref_get(E_OBJECT(bd)), bd->client.icccm.title,
5766           bd->client.icccm.name, bd->client.icccm.class);
5767    //   e_object_breadcrumb_debug(E_OBJECT(bd));
5768    printf("---\n");
5769    return 1;
5770    }
5771  */
5772
5773 static void
5774 _e_border_del(E_Border *bd)
5775 {
5776    E_Event_Border_Remove *ev;
5777    E_Border *child;
5778
5779 #ifdef _F_BORDER_HOOK_PATCH_
5780    _e_border_hook_call(E_BORDER_HOOK_DEL_BORDER, bd);
5781 #endif
5782
5783    if (bd == focused)
5784      {
5785         focused = NULL;
5786      }
5787
5788    if (bd == focusing)
5789      focusing = NULL;
5790
5791    focus_next = eina_list_remove(focus_next, bd);
5792
5793    if (bd->fullscreen) bd->desk->fullscreen_borders--;
5794
5795    if ((drag_border) && (drag_border->data == bd))
5796      {
5797         e_object_del(E_OBJECT(drag_border));
5798         drag_border = NULL;
5799      }
5800    if (bd->border_menu) e_menu_deactivate(bd->border_menu);
5801
5802    if (bd->border_locks_dialog)
5803      {
5804         e_object_del(E_OBJECT(bd->border_locks_dialog));
5805         bd->border_locks_dialog = NULL;
5806      }
5807    if (bd->border_remember_dialog)
5808      {
5809         e_object_del(E_OBJECT(bd->border_remember_dialog));
5810         bd->border_remember_dialog = NULL;
5811      }
5812    if (bd->border_border_dialog)
5813      {
5814         e_object_del(E_OBJECT(bd->border_border_dialog));
5815         bd->border_border_dialog = NULL;
5816      }
5817    if (bd->border_prop_dialog)
5818      {
5819         e_object_del(E_OBJECT(bd->border_prop_dialog));
5820         bd->border_prop_dialog = NULL;
5821      }
5822
5823    e_int_border_menu_del(bd);
5824
5825    if (bd->raise_timer)
5826      {
5827         ecore_timer_del(bd->raise_timer);
5828         bd->raise_timer = NULL;
5829      }
5830    if (!bd->already_unparented)
5831      {
5832         ecore_x_window_reparent(bd->client.win,
5833                                 bd->zone->container->manager->root,
5834                                 bd->x + bd->client_inset.l,
5835                                 bd->y + bd->client_inset.t);
5836         ecore_x_window_save_set_del(bd->client.win);
5837         bd->already_unparented = 1;
5838 //      bd->client.win = 0;
5839      }
5840    bd->already_unparented = 1;
5841
5842    if ((!bd->new_client) && (!stopping))
5843      {
5844         ev = E_NEW(E_Event_Border_Remove, 1);
5845         ev->border = bd;
5846         e_object_ref(E_OBJECT(bd));
5847         // e_object_breadcrumb_add(E_OBJECT(bd), "border_remove_event");
5848         ecore_event_add(E_EVENT_BORDER_REMOVE, ev, _e_border_event_border_remove_free, NULL);
5849      }
5850
5851    if (bd->parent)
5852      {
5853         bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
5854         if (bd->parent->modal == bd)
5855           {
5856              ecore_x_event_mask_unset(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
5857              ecore_x_event_mask_set(bd->parent->client.win, bd->parent->saved.event_mask);
5858              bd->parent->lock_close = 0;
5859              bd->parent->saved.event_mask = 0;
5860              bd->parent->modal = NULL;
5861           }
5862         bd->parent = NULL;
5863      }
5864    EINA_LIST_FREE(bd->transients, child)
5865      {
5866         child->parent = NULL;
5867      }
5868
5869 #ifdef _F_DEICONIFY_APPROVE_
5870    bd->client.e.state.deiconify_approve.render_done = 0;
5871
5872    E_Border *ancestor_bd;
5873    ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
5874    if ((ancestor_bd) &&
5875        (!e_object_is_del(E_OBJECT(ancestor_bd))))
5876      {
5877         ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
5878         bd->client.e.state.deiconify_approve.ancestor = NULL;
5879
5880         if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
5881             (ancestor_bd->client.e.state.deiconify_approve.render_done))
5882           {
5883              if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
5884                {
5885                   ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
5886                   ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
5887                   e_border_uniconify(ancestor_bd);
5888                }
5889           }
5890      }
5891
5892    if (bd->client.e.state.deiconify_approve.wait_timer)
5893      {
5894         ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer);
5895         bd->client.e.state.deiconify_approve.wait_timer = NULL;
5896      }
5897
5898    if (bd->client.e.state.deiconify_approve.req_list)
5899      {
5900         EINA_LIST_FREE(bd->client.e.state.deiconify_approve.req_list, child)
5901           {
5902              child->client.e.state.deiconify_approve.render_done = 0;
5903              child->client.e.state.deiconify_approve.ancestor = NULL;
5904           }
5905      }
5906 #endif
5907
5908 #ifdef _F_ZONE_WINDOW_ROTATION_
5909    if (rot.list) _e_border_rotation_list_remove(bd);
5910    if (rot.async_list)
5911      {
5912         Eina_List *l;
5913         E_Border_Rotation_Info *info = NULL;
5914
5915         EINA_LIST_FOREACH(rot.async_list, l, info)
5916            if (info->bd == bd)
5917              {
5918                 rot.async_list = eina_list_remove(rot.async_list, info);
5919                 E_FREE(info);
5920              }
5921      }
5922 #endif
5923
5924    if (bd->leader)
5925      {
5926         bd->leader->group = eina_list_remove(bd->leader->group, bd);
5927         if (bd->leader->modal == bd)
5928           bd->leader->modal = NULL;
5929         bd->leader = NULL;
5930      }
5931    EINA_LIST_FREE(bd->group, child)
5932      {
5933         child->leader = NULL;
5934      }
5935 }
5936
5937 #ifdef PRINT_LOTS_OF_DEBUG
5938 static void
5939 _e_border_print(E_Border   *bd,
5940                 const char *func)
5941 {
5942    if (!bd) return;
5943
5944    DBG("*Window Info*"
5945           "\tPointer: %p\n"
5946           "\tName: %s\n"
5947           "\tTitle: %s\n"
5948           "\tBorderless: %s\n",
5949           bd, bd->client.icccm.name, bd->client.icccm.title,
5950           bd->borderless ? "TRUE" : "FALSE");
5951 }
5952
5953 #endif
5954
5955 static Eina_Bool
5956 _e_border_cb_window_show_request(void *data  __UNUSED__,
5957                                  int ev_type __UNUSED__,
5958                                  void       *ev)
5959 {
5960    E_Border *bd;
5961    E_Container *con;
5962    Ecore_X_Event_Window_Show_Request *e;
5963
5964    e = ev;
5965    bd = e_border_find_by_client_window(e->win);
5966    if (!bd) return ECORE_CALLBACK_PASS_ON;
5967
5968    if ((e_config->wm_win_rotation) &&
5969        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
5970        (bd == rot.vkbd) &&
5971        (rot.vkbd_hide_prepare_timer))
5972      {
5973         con = bd->zone->container;
5974         bd = e_border_new(con, e->win, 0, 0);
5975      }
5976
5977    if (bd->iconic)
5978      {
5979         if (!bd->lock_client_iconify)
5980           e_border_uniconify(bd);
5981      }
5982    else
5983      {
5984         /* FIXME: make border "urgent" for a bit - it wants attention */
5985 /*      e_border_show(bd); */
5986           if (!bd->lock_client_stacking)
5987             e_border_raise(bd);
5988      }
5989    return ECORE_CALLBACK_PASS_ON;
5990 }
5991
5992 static Eina_Bool
5993 _e_border_cb_window_destroy(void *data  __UNUSED__,
5994                             int ev_type __UNUSED__,
5995                             void       *ev)
5996 {
5997    E_Border *bd;
5998    Ecore_X_Event_Window_Destroy *e;
5999
6000    e = ev;
6001    bd = e_border_find_by_client_window(e->win);
6002    if (!bd) return ECORE_CALLBACK_PASS_ON;
6003    ELB(ELBT_BD, "X_WIN_DEL", bd->client.win);
6004 #ifdef _F_ZONE_WINDOW_ROTATION_
6005    if (e_config->wm_win_rotation)
6006      {
6007         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
6008           {
6009              ELB(ELBT_BD, "X_DEL_NOTIFY", bd->client.win);
6010              if (!rot.vkbd_hide_prepare_timer)
6011                {
6012                   ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
6013                   e_border_hide(bd, 0);
6014                   if (!rot.vkbd_hide_prepare_timer)
6015                     {
6016                        ELB(ELBT_BD, "DEL VKBD", bd->client.win);
6017                        e_object_del(E_OBJECT(bd));
6018                     }
6019                }
6020              return ECORE_CALLBACK_PASS_ON;
6021           }
6022      }
6023 #endif
6024    e_border_hide(bd, 0);
6025    e_object_del(E_OBJECT(bd));
6026    return ECORE_CALLBACK_PASS_ON;
6027 }
6028
6029 static Eina_Bool
6030 _e_border_cb_window_hide(void *data  __UNUSED__,
6031                          int ev_type __UNUSED__,
6032                          void       *ev)
6033 {
6034    E_Border *bd = NULL;
6035    Ecore_X_Event_Window_Hide *e;
6036
6037    e = ev;
6038 //   printf("HIDE: %x, event %x send: %i\n", e->win, e->event_win, e->send_event);
6039 // not interested in hide events from windows other than the window in question
6040    if (e->win != e->event_win)
6041      {
6042         bd = e_border_find_by_client_window(e->win);
6043         if (!bd) return ECORE_CALLBACK_PASS_ON;
6044         if (!e->send_event) return ECORE_CALLBACK_PASS_ON;
6045         else
6046           {
6047              if (!((bd->zone) &&
6048                    (bd->zone->container->manager->root == e->event_win)))
6049                return ECORE_CALLBACK_PASS_ON;
6050           }
6051      }
6052    if (!bd) bd = e_border_find_by_client_window(e->win);
6053 //   printf("  bd = %p\n", bd);
6054    if (!bd)
6055      {
6056         if (ecore_x_window_visible_get(e->win))
6057           {
6058              ELB(ELBT_BD, "FORCE UNMAP client window", e->win);
6059              ecore_x_window_hide(e->win);
6060           }
6061         return ECORE_CALLBACK_PASS_ON;
6062      }
6063
6064 //   printf("  bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap);
6065    if (bd->ignore_first_unmap > 0)
6066      {
6067         bd->ignore_first_unmap--;
6068         return ECORE_CALLBACK_PASS_ON;
6069      }
6070    /* Don't delete hidden or iconified windows */
6071 #ifdef _F_USE_EXTENDED_ICONIFY_
6072    if (bd->await_hide_event > 0)
6073 #else
6074    if ((bd->iconic) || (bd->await_hide_event > 0))
6075 #endif
6076      {
6077 //        printf("  Don't delete hidden or iconified windows\n");
6078 //        printf("  bd->iconic = %i, bd->visible = %i, bd->new_client = %i, bd->await_hide_event = %i\n",
6079 //               bd->iconic, bd->visible, bd->new_client, bd->await_hide_event);
6080         if (bd->await_hide_event > 0)
6081           {
6082              bd->await_hide_event--;
6083           }
6084         else
6085           {
6086 //             printf("  hide really\n");
6087              /* Only hide the border if it is visible */
6088              if (bd->visible) e_border_hide(bd, 1);
6089           }
6090      }
6091    else
6092      {
6093 //             printf("  hide2\n");
6094 #ifdef _F_USE_EXTENDED_ICONIFY_
6095         if (bd->iconic)
6096           {
6097              bd->iconic = 0;
6098              bd->visible = 1;
6099           }
6100 #endif
6101
6102 #ifdef _F_ZONE_WINDOW_ROTATION_
6103         if (e_config->wm_win_rotation)
6104           {
6105              if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
6106                {
6107                   ELB(ELBT_BD, "X_UNMAP_NOTIFY", bd->client.win);
6108                   if (!rot.vkbd_hide_prepare_timer)
6109                     {
6110                        ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
6111                        e_border_hide(bd, 0);
6112                        if (!rot.vkbd_hide_prepare_timer)
6113                          {
6114                             ELB(ELBT_BD, "DEL VKBD", bd->client.win);
6115                             e_object_del(E_OBJECT(bd));
6116                          }
6117                     }
6118                   return ECORE_CALLBACK_PASS_ON;
6119                }
6120           }
6121 #endif
6122         e_border_hide(bd, 0);
6123         e_object_del(E_OBJECT(bd));
6124      }
6125    return ECORE_CALLBACK_PASS_ON;
6126 }
6127
6128 static Eina_Bool
6129 _e_border_cb_window_reparent(void *data  __UNUSED__,
6130                              int ev_type __UNUSED__,
6131                              void *ev    __UNUSED__)
6132 {
6133 #if 0
6134    E_Border *bd;
6135    Ecore_X_Event_Window_Reparent *e;
6136
6137    e = ev;
6138    bd = e_border_find_by_client_window(e->win);
6139    if (!bd) return 1;
6140    if (e->parent == bd->client.shell_win) return 1;
6141    if (ecore_x_window_parent_get(e->win) == bd->client.shell_win)
6142      {
6143         return 1;
6144      }
6145    e_border_hide(bd, 0);
6146    e_object_del(E_OBJECT(bd));
6147 #endif
6148    return ECORE_CALLBACK_PASS_ON;
6149 }
6150
6151 static Eina_Bool
6152 _e_border_cb_window_configure_request(void *data  __UNUSED__,
6153                                       int ev_type __UNUSED__,
6154                                       void       *ev)
6155 {
6156    E_Border *bd;
6157    Ecore_X_Event_Window_Configure_Request *e;
6158
6159    e = ev;
6160    bd = e_border_find_by_client_window(e->win);
6161    if (!bd)
6162      {
6163         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6164         if (!e_util_container_window_find(e->win))
6165           ecore_x_window_configure(e->win, e->value_mask,
6166                                    e->x, e->y, e->w, e->h, e->border,
6167                                    e->abovewin, e->detail);
6168         return ECORE_CALLBACK_PASS_ON;
6169      }
6170
6171    if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
6172        (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
6173      {
6174         int x, y;
6175
6176         x = bd->x;
6177         y = bd->y;
6178         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
6179           x = e->x;
6180         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
6181           y = e->y;
6182         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6183             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6184           {
6185              int w, h;
6186
6187              h = bd->h;
6188              w = bd->w;
6189              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6190                w = e->w + bd->client_inset.l + bd->client_inset.r;
6191              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6192                h = e->h + bd->client_inset.t + bd->client_inset.b;
6193              if ((!bd->lock_client_location) && (!bd->lock_client_size))
6194                {
6195                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6196                     {
6197                        bd->saved.x = x - bd->zone->x;
6198                        bd->saved.y = y - bd->zone->y;
6199                        bd->saved.w = w;
6200                        bd->saved.h = h;
6201                     }
6202                   else
6203                     e_border_move_resize(bd, x, y, w, h);
6204                }
6205              else if (!bd->lock_client_location)
6206                {
6207                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6208                     {
6209                        bd->saved.x = x - bd->zone->x;
6210                        bd->saved.y = y - bd->zone->y;
6211                     }
6212                   else
6213                     e_border_move(bd, x, y);
6214                }
6215              else if (!bd->lock_client_size)
6216                {
6217                   if ((bd->shaded) || (bd->shading))
6218                     {
6219                        int pw, ph;
6220
6221                        pw = bd->client.w;
6222                        ph = bd->client.h;
6223                        if ((bd->shade.dir == E_DIRECTION_UP) ||
6224                            (bd->shade.dir == E_DIRECTION_DOWN))
6225                          {
6226                             e_border_resize(bd, w, bd->h);
6227                             bd->client.h = ph;
6228                          }
6229                        else
6230                          {
6231                             e_border_resize(bd, bd->w, h);
6232                             bd->client.w = pw;
6233                          }
6234                     }
6235                   else
6236                     {
6237                        if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6238                          {
6239                             bd->saved.w = w;
6240                             bd->saved.h = h;
6241                          }
6242                        else
6243                          e_border_resize(bd, w, h);
6244                     }
6245                }
6246           }
6247         else
6248           {
6249              if (!bd->lock_client_location)
6250                {
6251                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6252                     {
6253                        bd->saved.x = x - bd->zone->x;
6254                        bd->saved.y = y - bd->zone->y;
6255                     }
6256                   else
6257                     e_border_move(bd, x, y);
6258                }
6259           }
6260      }
6261    else if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6262             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6263      {
6264         int w, h;
6265
6266         h = bd->h;
6267         w = bd->w;
6268         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6269           w = e->w + bd->client_inset.l + bd->client_inset.r;
6270         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6271           h = e->h + bd->client_inset.t + bd->client_inset.b;
6272 #ifdef _F_ZONE_WINDOW_ROTATION_
6273         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
6274 #endif
6275         if (!bd->lock_client_size)
6276           {
6277              if ((bd->shaded) || (bd->shading))
6278                {
6279                   int pw, ph;
6280
6281                   pw = bd->client.w;
6282                   ph = bd->client.h;
6283                   if ((bd->shade.dir == E_DIRECTION_UP) ||
6284                       (bd->shade.dir == E_DIRECTION_DOWN))
6285                     {
6286                        e_border_resize(bd, w, bd->h);
6287                        bd->client.h = ph;
6288                     }
6289                   else
6290                     {
6291                        e_border_resize(bd, bd->w, h);
6292                        bd->client.w = pw;
6293                     }
6294                }
6295              else
6296                {
6297                   if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE)
6298                     {
6299                        int zx, zy, zw, zh;
6300                        int rx = bd->x;
6301                        int ry = bd->y;
6302                        zx = zy = zw = zh = 0;
6303
6304      /*
6305       * This code does resize and move a window on a
6306       * X configure request into an useful geometry.
6307       * This is really useful for size jumping file dialogs.
6308       */
6309
6310                        if (bd->zone)
6311                          {
6312                             e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
6313
6314                             if (e_config->geometry_auto_resize_limit == 1)
6315                               {
6316                                  if (w > zw)
6317                                    w = zw;
6318
6319                                  if (h > zh)
6320                                    h = zh;
6321                               }
6322                          }
6323                        e_border_resize(bd, w, h);
6324
6325                        if (e_config->geometry_auto_move == 1)
6326                          {
6327                              /* z{x,y,w,h} are only set here; FIXME! */
6328                              if (bd->zone)
6329                                {
6330                                   // move window horizontal if resize to not useful geometry
6331                                   if (bd->x + bd->w > zx + zw)
6332                                     rx = zx + zw - bd->w;
6333                                   else if (bd->x < zx)
6334                                     rx = zx;
6335
6336                                   // move window vertical if resize to not useful geometry
6337                                   if (bd->y + bd->h > zy + zh)
6338                                     ry = zy + zh - bd->h;
6339                                   else if (bd->y < zy)
6340                                     ry = zy;
6341                                }
6342                              e_border_move(bd, rx, ry);
6343                          }
6344                     }
6345                }
6346           }
6347      }
6348    if (!bd->lock_client_stacking)
6349      {
6350         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
6351             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
6352           {
6353              E_Border *obd;
6354
6355              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6356                {
6357                   obd = e_border_find_by_client_window(e->abovewin);
6358                   if (obd)
6359                     {
6360                        e_border_stack_above(bd, obd);
6361                     }
6362                   else
6363                     {
6364                        ecore_x_window_configure(bd->win,
6365                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6366                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6367                                                 0, 0, 0, 0, 0,
6368                                                 e->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
6369                        /* FIXME: need to rebuiuld border list from current stacking */
6370                     }
6371                }
6372              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6373                {
6374                   obd = e_border_find_by_client_window(e->abovewin);
6375                   if (obd)
6376                     {
6377                        e_border_stack_below(bd, obd);
6378                     }
6379                   else
6380                     {
6381                        ecore_x_window_configure(bd->win,
6382                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6383                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6384                                                 0, 0, 0, 0, 0,
6385                                                 e->abovewin, ECORE_X_WINDOW_STACK_BELOW);
6386                        /* FIXME: need to rebuiuld border list from current stacking */
6387                     }
6388                }
6389              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6390                {
6391      /* FIXME: do */
6392                }
6393              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6394                {
6395      /* FIXME: do */
6396                }
6397              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6398                {
6399      /* FIXME: do */
6400                }
6401           }
6402         else if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
6403           {
6404              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6405                {
6406                   e_border_raise(bd);
6407                }
6408              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6409                {
6410                   e_border_lower(bd);
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      }
6426
6427    /* FIXME: need to send synthetic stacking event too as well as move/resize */
6428    _e_border_client_move_resize_send(bd);
6429    return ECORE_CALLBACK_PASS_ON;
6430 }
6431
6432 static Eina_Bool
6433 _e_border_cb_window_resize_request(void *data  __UNUSED__,
6434                                    int ev_type __UNUSED__,
6435                                    void       *ev)
6436 {
6437    E_Border *bd;
6438    Ecore_X_Event_Window_Resize_Request *e;
6439
6440    e = ev;
6441    bd = e_border_find_by_client_window(e->win);
6442    if (!bd)
6443      {
6444         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6445         ecore_x_window_resize(e->win, e->w, e->h);
6446         return ECORE_CALLBACK_PASS_ON;
6447      }
6448    {
6449       int w, h;
6450
6451       w = e->w + bd->client_inset.l + bd->client_inset.r;
6452       h = e->h + bd->client_inset.t + bd->client_inset.b;
6453       if ((bd->shaded) || (bd->shading))
6454         {
6455            int pw, ph;
6456
6457            pw = bd->client.w;
6458            ph = bd->client.h;
6459            if ((bd->shade.dir == E_DIRECTION_UP) ||
6460                (bd->shade.dir == E_DIRECTION_DOWN))
6461              {
6462                 e_border_resize(bd, w, bd->h);
6463                 bd->client.h = ph;
6464              }
6465            else
6466              {
6467                 e_border_resize(bd, bd->w, h);
6468                 bd->client.w = pw;
6469              }
6470         }
6471       else
6472         e_border_resize(bd, w, h);
6473    }
6474
6475    _e_border_client_move_resize_send(bd);
6476    return ECORE_CALLBACK_PASS_ON;
6477 }
6478
6479 static Eina_Bool
6480 _e_border_cb_window_gravity(void *data  __UNUSED__,
6481                             int ev_type __UNUSED__,
6482                             void *ev    __UNUSED__)
6483 {
6484 //   E_Border *bd;
6485 //   Ecore_X_Event_Window_Gravity *e;
6486
6487 //   e = ev;
6488 //   bd = e_border_find_by_client_window(e->win);
6489 //   if (!bd) return 1;
6490              return 1;
6491 }
6492
6493 static Eina_Bool
6494 _e_border_cb_window_stack_request(void *data  __UNUSED__,
6495                                   int ev_type __UNUSED__,
6496                                   void       *ev)
6497 {
6498    E_Border *bd;
6499    Ecore_X_Event_Window_Stack_Request *e;
6500
6501    e = ev;
6502    bd = e_border_find_by_client_window(e->win);
6503    if (!bd)
6504      {
6505         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6506         if (!e_util_container_window_find(e->win))
6507           {
6508              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6509                ecore_x_window_raise(e->win);
6510              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6511                ecore_x_window_lower(e->win);
6512           }
6513         return ECORE_CALLBACK_PASS_ON;
6514      }
6515    if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6516      e_border_raise(bd);
6517    else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6518      e_border_lower(bd);
6519    return ECORE_CALLBACK_PASS_ON;
6520 }
6521
6522 static Eina_Bool
6523 _e_border_cb_window_property(void *data  __UNUSED__,
6524                              int ev_type __UNUSED__,
6525                              void       *ev)
6526 {
6527    E_Border *bd;
6528    Ecore_X_Event_Window_Property *e;
6529
6530    e = ev;
6531    bd = e_border_find_by_client_window(e->win);
6532    if (!bd) return ECORE_CALLBACK_PASS_ON;
6533    if (e->atom == ECORE_X_ATOM_WM_NAME)
6534      {
6535         if ((!bd->client.netwm.name) &&
6536             (!bd->client.netwm.fetch.name))
6537           {
6538              bd->client.icccm.fetch.title = 1;
6539              bd->changed = 1;
6540           }
6541      }
6542    else if (e->atom == ECORE_X_ATOM_NET_WM_NAME)
6543      {
6544         bd->client.netwm.fetch.name = 1;
6545         bd->changed = 1;
6546      }
6547    else if (e->atom == ECORE_X_ATOM_WM_CLASS)
6548      {
6549         bd->client.icccm.fetch.name_class = 1;
6550         bd->changed = 1;
6551      }
6552    else if (e->atom == ECORE_X_ATOM_WM_ICON_NAME)
6553      {
6554         if ((!bd->client.netwm.icon_name) &&
6555             (!bd->client.netwm.fetch.icon_name))
6556           {
6557              bd->client.icccm.fetch.icon_name = 1;
6558              bd->changed = 1;
6559           }
6560      }
6561    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
6562      {
6563         bd->client.netwm.fetch.icon_name = 1;
6564         bd->changed = 1;
6565      }
6566    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
6567      {
6568         bd->client.icccm.fetch.machine = 1;
6569         bd->changed = 1;
6570      }
6571    else if (e->atom == ECORE_X_ATOM_WM_PROTOCOLS)
6572      {
6573         bd->client.icccm.fetch.protocol = 1;
6574         bd->changed = 1;
6575      }
6576    else if (e->atom == ECORE_X_ATOM_WM_HINTS)
6577      {
6578         bd->client.icccm.fetch.hints = 1;
6579         bd->changed = 1;
6580      }
6581    else if (e->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
6582      {
6583         bd->client.icccm.fetch.size_pos_hints = 1;
6584         bd->changed = 1;
6585      }
6586    else if (e->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
6587      {
6588         /*
6589            if ((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN) &&
6590             (!bd->client.netwm.fetch.type))
6591            {
6592          */
6593           bd->client.mwm.fetch.hints = 1;
6594           bd->changed = 1;
6595           /*
6596              }
6597            */
6598      }
6599    else if (e->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
6600      {
6601         bd->client.icccm.fetch.transient_for = 1;
6602         bd->changed = 1;
6603      }
6604    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
6605      {
6606         bd->client.icccm.fetch.client_leader = 1;
6607         bd->changed = 1;
6608      }
6609    else if (e->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
6610      {
6611         bd->client.icccm.fetch.window_role = 1;
6612         bd->changed = 1;
6613      }
6614    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON)
6615      {
6616         bd->client.netwm.fetch.icon = 1;
6617         bd->changed = 1;
6618      }
6619    else if (e->atom == ATM__QTOPIA_SOFT_MENU)
6620      {
6621         bd->client.qtopia.fetch.soft_menu = 1;
6622         bd->changed = 1;
6623      }
6624    else if (e->atom == ATM__QTOPIA_SOFT_MENUS)
6625      {
6626         bd->client.qtopia.fetch.soft_menus = 1;
6627         bd->changed = 1;
6628      }
6629    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
6630      {
6631         bd->client.vkbd.fetch.state = 1;
6632         bd->changed = 1;
6633      }
6634    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
6635      {
6636         bd->client.vkbd.fetch.vkbd = 1;
6637         bd->changed = 1;
6638      }
6639    else if (e->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
6640      {
6641         bd->client.illume.conformant.fetch.conformant = 1;
6642         bd->changed = 1;
6643      }
6644    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
6645      {
6646         bd->client.illume.quickpanel.fetch.state = 1;
6647         bd->changed = 1;
6648      }
6649    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
6650      {
6651         bd->client.illume.quickpanel.fetch.quickpanel = 1;
6652         bd->changed = 1;
6653      }
6654    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
6655      {
6656         bd->client.illume.quickpanel.fetch.priority.major = 1;
6657         bd->changed = 1;
6658      }
6659    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
6660      {
6661         bd->client.illume.quickpanel.fetch.priority.minor = 1;
6662         bd->changed = 1;
6663      }
6664    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
6665      {
6666         bd->client.illume.quickpanel.fetch.zone = 1;
6667         bd->changed = 1;
6668      }
6669    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
6670      {
6671         bd->client.illume.drag.fetch.locked = 1;
6672         bd->changed = 1;
6673      }
6674    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
6675      {
6676         bd->client.illume.drag.fetch.drag = 1;
6677         bd->changed = 1;
6678      }
6679    else if (e->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
6680      {
6681         bd->client.illume.win_state.fetch.state = 1;
6682         bd->changed = 1;
6683      }
6684    /*
6685       else if (e->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
6686       {
6687         bd->client.netwm.fetch.user_time = 1;
6688         bd->changed = 1;
6689       }
6690       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT)
6691       {
6692         bd->client.netwm.fetch.strut = 1;
6693         bd->changed = 1;
6694       }
6695       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
6696       {
6697         bd->client.netwm.fetch.strut = 1;
6698         bd->changed = 1;
6699       }
6700     */
6701    else if (e->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
6702      {
6703         //printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
6704      }
6705    else if (e->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
6706      {
6707         bd->client.e.fetch.video_position = 1;
6708         bd->changed = 1;
6709      }
6710    else if (e->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
6711      {
6712         bd->client.e.fetch.video_parent = 1;
6713         bd->changed = 1;
6714      }
6715    else if (e->atom == ECORE_X_ATOM_NET_WM_STATE)
6716      {
6717         bd->client.netwm.fetch.state = 1;
6718         bd->changed = 1;
6719      }
6720 #ifdef _F_USE_DESK_WINDOW_PROFILE_
6721    else if (e->atom == ECORE_X_ATOM_E_PROFILE_LIST)
6722      {
6723         bd->client.e.fetch.profile_list = 1;
6724         bd->changed = 1;
6725      }
6726 #endif
6727 #ifdef _F_ZONE_WINDOW_ROTATION_
6728    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED)
6729      {
6730         if (e_config->wm_win_rotation)
6731           {
6732              bd->client.e.fetch.rot.support = 1;
6733              bd->changed = 1;
6734           }
6735      }
6736    else if ((e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) ||
6737             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) ||
6738             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) ||
6739             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY))
6740      {
6741         if (e_config->wm_win_rotation)
6742           {
6743              bd->client.e.fetch.rot.geom_hint = 1;
6744              bd->changed = 1;
6745           }
6746      }
6747    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED)
6748      {
6749         if (e_config->wm_win_rotation)
6750           {
6751              bd->client.e.fetch.rot.app_set = 1;
6752              bd->changed = 1;
6753           }
6754      }
6755    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION)
6756      {
6757         if (e_config->wm_win_rotation)
6758           {
6759              bd->client.e.fetch.rot.preferred_rot = 1;
6760              bd->changed = 1;
6761           }
6762      }
6763    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)
6764      {
6765         if (e_config->wm_win_rotation)
6766           {
6767              bd->client.e.fetch.rot.available_rots = 1;
6768              bd->changed = 1;
6769           }
6770      }
6771 #endif
6772
6773    return ECORE_CALLBACK_PASS_ON;
6774 }
6775
6776 static Eina_Bool
6777 _e_border_cb_window_colormap(void *data  __UNUSED__,
6778                              int ev_type __UNUSED__,
6779                              void       *ev)
6780 {
6781    E_Border *bd;
6782    Ecore_X_Event_Window_Colormap *e;
6783
6784    e = ev;
6785    bd = e_border_find_by_client_window(e->win);
6786    if (!bd) return ECORE_CALLBACK_PASS_ON;
6787    return ECORE_CALLBACK_PASS_ON;
6788 }
6789
6790 static Eina_Bool
6791 _e_border_cb_window_shape(void *data  __UNUSED__,
6792                           int ev_type __UNUSED__,
6793                           void       *ev)
6794 {
6795    E_Border *bd;
6796    Ecore_X_Event_Window_Shape *e;
6797
6798    e = ev;
6799    bd = e_border_find_by_client_window(e->win);
6800
6801    if (e->type == ECORE_X_SHAPE_INPUT)
6802      {
6803         if (bd)
6804           {
6805              bd->need_shape_merge = 1;
6806 // YYY             bd->shaped_input = 1;
6807              bd->changes.shape_input = 1;
6808              bd->changed = 1;
6809           }
6810
6811         return ECORE_CALLBACK_PASS_ON;
6812      }
6813
6814    if (bd)
6815      {
6816         bd->changes.shape = 1;
6817         bd->changed = 1;
6818         return ECORE_CALLBACK_PASS_ON;
6819      }
6820    bd = e_border_find_by_window(e->win);
6821    if (bd)
6822      {
6823         bd->need_shape_export = 1;
6824         bd->changed = 1;
6825         return ECORE_CALLBACK_PASS_ON;
6826      }
6827    bd = e_border_find_by_frame_window(e->win);
6828    if (bd)
6829      {
6830         bd->need_shape_merge = 1;
6831         bd->changed = 1;
6832         return ECORE_CALLBACK_PASS_ON;
6833      }
6834    return ECORE_CALLBACK_PASS_ON;
6835 }
6836
6837 static Eina_Bool
6838 _e_border_cb_window_focus_in(void *data  __UNUSED__,
6839                              int ev_type __UNUSED__,
6840                              void       *ev)
6841 {
6842    E_Border *bd;
6843    Ecore_X_Event_Window_Focus_In *e;
6844
6845    e = ev;
6846    bd = e_border_find_by_client_window(e->win);
6847    if (!bd) return ECORE_CALLBACK_PASS_ON;
6848 #ifdef INOUTDEBUG_FOCUS
6849    {
6850       time_t t;
6851       char *ct;
6852
6853       const char *modes[] = {
6854         "MODE_NORMAL",
6855         "MODE_WHILE_GRABBED",
6856         "MODE_GRAB",
6857         "MODE_UNGRAB"
6858       };
6859       const char *details[] = {
6860         "DETAIL_ANCESTOR",
6861         "DETAIL_VIRTUAL",
6862         "DETAIL_INFERIOR",
6863         "DETAIL_NON_LINEAR",
6864         "DETAIL_NON_LINEAR_VIRTUAL",
6865         "DETAIL_POINTER",
6866         "DETAIL_POINTER_ROOT",
6867         "DETAIL_DETAIL_NONE"
6868       };
6869       t = time(NULL);
6870       ct = ctime(&t);
6871       ct[strlen(ct) - 1] = 0;
6872       DBG("FF ->IN %i 0x%x %s md=%s dt=%s\n",
6873              e->time,
6874              e->win,
6875              ct,
6876              modes[e->mode],
6877              details[e->detail]);
6878
6879       DBG("%s cb focus in %d %d\n",
6880              e_border_name_get(bd),
6881              bd->client.icccm.accepts_focus,
6882              bd->client.icccm.take_focus);
6883    }
6884 #endif
6885    _e_border_pri_raise(bd);
6886    if (e->mode == ECORE_X_EVENT_MODE_GRAB)
6887      {
6888         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
6889      }
6890    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
6891      {
6892         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
6893      }
6894
6895    /* ignore focus in from !take_focus windows, we just gave it em */
6896    /* if (!bd->client.icccm.take_focus)
6897     *   return ECORE_CALLBACK_PASS_ON; */
6898
6899    /* should be equal, maybe some clients dont reply with the proper timestamp ? */
6900    if (e->time >= focus_time)
6901      e_border_focus_set(bd, 1, 0);
6902    return ECORE_CALLBACK_PASS_ON;
6903 }
6904
6905 static Eina_Bool
6906 _e_border_cb_window_focus_out(void *data  __UNUSED__,
6907                               int ev_type __UNUSED__,
6908                               void       *ev)
6909 {
6910    E_Border *bd;
6911    Ecore_X_Event_Window_Focus_Out *e;
6912
6913    e = ev;
6914    bd = e_border_find_by_client_window(e->win);
6915    if (!bd) return ECORE_CALLBACK_PASS_ON;
6916 #ifdef INOUTDEBUG_FOCUS
6917    {
6918       time_t t;
6919       char *ct;
6920
6921       const char *modes[] = {
6922         "MODE_NORMAL",
6923         "MODE_WHILE_GRABBED",
6924         "MODE_GRAB",
6925         "MODE_UNGRAB"
6926       };
6927       const char *details[] = {
6928         "DETAIL_ANCESTOR",
6929         "DETAIL_VIRTUAL",
6930         "DETAIL_INFERIOR",
6931         "DETAIL_NON_LINEAR",
6932         "DETAIL_NON_LINEAR_VIRTUAL",
6933         "DETAIL_POINTER",
6934         "DETAIL_POINTER_ROOT",
6935         "DETAIL_DETAIL_NONE"
6936       };
6937       t = time(NULL);
6938       ct = ctime(&t);
6939       ct[strlen(ct) - 1] = 0;
6940       DBG("FF <-OUT %i 0x%x %s md=%s dt=%s",
6941              e->time,
6942              e->win,
6943              ct,
6944              modes[e->mode],
6945              details[e->detail]);
6946
6947       DBG("%s cb focus out %d %d",
6948              e_border_name_get(bd),
6949              bd->client.icccm.accepts_focus,
6950              bd->client.icccm.take_focus);
6951    }
6952 #endif
6953    _e_border_pri_norm(bd);
6954    if (e->mode == ECORE_X_EVENT_MODE_NORMAL)
6955      {
6956         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
6957         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
6958           return ECORE_CALLBACK_PASS_ON;
6959         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
6960           return ECORE_CALLBACK_PASS_ON;
6961      }
6962    else if (e->mode == ECORE_X_EVENT_MODE_GRAB)
6963      {
6964         if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR) return ECORE_CALLBACK_PASS_ON;
6965         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
6966           return ECORE_CALLBACK_PASS_ON;
6967         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
6968           return ECORE_CALLBACK_PASS_ON;
6969         else if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
6970           return ECORE_CALLBACK_PASS_ON;
6971         else if (e->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
6972           return ECORE_CALLBACK_PASS_ON;
6973      }
6974    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
6975      {
6976         /* for firefox/thunderbird (xul) menu walking */
6977         /* NB: why did i disable this before? */
6978         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
6979         else if (e->detail == ECORE_X_EVENT_DETAIL_POINTER)
6980           return ECORE_CALLBACK_PASS_ON;
6981      }
6982    else if (e->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
6983      {
6984         if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR) return ECORE_CALLBACK_PASS_ON;
6985         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
6986           return ECORE_CALLBACK_PASS_ON;
6987      }
6988    e_border_focus_set(bd, 0, 0);
6989    return ECORE_CALLBACK_PASS_ON;
6990 }
6991
6992 #if _F_BORDER_CLIP_TO_ZONE_
6993 static void
6994 _e_border_shape_input_clip_to_zone(E_Border *bd)
6995 {
6996    /* if (!(e_config->window_out_of_vscreen_limits_partly)) return; */
6997    if (!(bd->visible))
6998      return;
6999
7000    if (!(E_CONTAINS(bd->zone->x, bd->zone->y,
7001                     bd->zone->w, bd->zone->h,
7002                     bd->x, bd->y, bd->w, bd->h)))
7003      {
7004         int x, y, w, h;
7005         x = bd->x; y = bd->y; w = bd->w; h = bd->h;
7006         E_RECTS_CLIP_TO_RECT(x, y, w, h,
7007                              bd->zone->x, bd->zone->y,
7008                              bd->zone->w, bd->zone->h);
7009         x -= bd->x;
7010         y -= bd->y;
7011         ecore_x_window_shape_input_rectangle_set(bd->bg_win, x, y, w, h);
7012         ecore_x_window_shape_input_rectangle_set(bd->win, x, y, w, h);
7013      }
7014    else
7015      {
7016         ecore_x_window_shape_input_rectangle_set(bd->bg_win, 0, 0, bd->w, bd->h);
7017         ecore_x_window_shape_input_rectangle_set(bd->win, 0, 0, bd->w, bd->h);
7018      }
7019 }
7020 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
7021
7022 static Eina_Bool
7023 _e_border_cb_client_message(void *data  __UNUSED__,
7024                             int ev_type __UNUSED__,
7025                             void       *ev)
7026 {
7027    Ecore_X_Event_Client_Message *e;
7028    E_Border *bd;
7029
7030    e = ev;
7031 #ifdef _F_DEICONIFY_APPROVE_
7032    if (e->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
7033      {
7034         if (!e_config->deiconify_approve) return ECORE_CALLBACK_PASS_ON;
7035
7036         bd = e_border_find_by_client_window(e->win);
7037         if (bd)
7038           {
7039              if (bd->client.e.state.deiconify_approve.support)
7040                {
7041                   if (e->data.l[1] != 1) return ECORE_CALLBACK_PASS_ON;
7042                   bd->client.e.state.deiconify_approve.render_done = 1;
7043
7044                   E_Border *ancestor_bd;
7045                   ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
7046                   if (ancestor_bd)
7047                     {
7048                        ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
7049                        bd->client.e.state.deiconify_approve.ancestor = NULL;
7050                     }
7051                   else
7052                     {
7053                        ancestor_bd = bd;
7054                     }
7055
7056                   ELBF(ELBT_BD, 0, bd->client.win,
7057                        "RECEIVE DEICONIFY_APPROVE.. ancestor:%x", ancestor_bd->client.win);
7058
7059                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
7060                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
7061                     {
7062                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
7063                          {
7064                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
7065                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
7066                             e_border_uniconify(ancestor_bd);
7067                          }
7068                        else
7069                          {
7070                             ELB(ELBT_BD, "Unset DEICONIFY_APPROVE render_done", ancestor_bd->client.win);
7071                             ancestor_bd->client.e.state.deiconify_approve.render_done = 0;
7072                          }
7073                     }
7074                }
7075           }
7076         return ECORE_CALLBACK_PASS_ON;
7077      }
7078 #endif
7079
7080 #ifdef _F_ZONE_WINDOW_ROTATION_
7081    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
7082
7083    bd = e_border_find_by_client_window(e->win);
7084    if (!bd)
7085      {
7086         if (e_config->wm_win_rotation)
7087           {
7088              Ecore_X_Event_Client_Message *msg = NULL;
7089              Ecore_X_Atom t = e->message_type;
7090              if ((t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)  ||
7091                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE) ||
7092                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)   ||
7093                  (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE))
7094                {
7095                   msg = E_NEW(Ecore_X_Event_Client_Message, 1);
7096                   if (!msg) return ECORE_CALLBACK_PASS_ON;
7097
7098                   msg->win = e->win;
7099                   msg->message_type = e->message_type;
7100                   msg->data.l[0] = e->data.l[0];
7101                   msg->data.l[1] = e->data.l[1];
7102                   msg->data.l[2] = e->data.l[2];
7103                   msg->data.l[3] = e->data.l[3];
7104                   msg->data.l[4] = e->data.l[4];
7105                   rot.msgs = eina_list_append(rot.msgs, msg);
7106
7107                   rot.fetch = EINA_TRUE;
7108                }
7109           }
7110         return ECORE_CALLBACK_PASS_ON;
7111      }
7112
7113    if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE)
7114      {
7115         ELBF(ELBT_ROT, 0, e->data.l[0], "GET ROT_DONE a%d %dx%d zone_a:%d",
7116              e->data.l[1], e->data.l[2], e->data.l[3], bd->zone->rot.curr);
7117
7118         if (e_config->wm_win_rotation)
7119           {
7120              if ((int)e->data.l[1] == bd->client.e.state.rot.curr)
7121                {
7122                   _e_border_rotation_list_remove(bd);
7123                   if (bd->client.e.state.rot.pending_show)
7124                     {
7125                        ELB(ELBT_BD, "SHOW_BD (PEND)", bd->client.win);
7126                        e_border_show(bd);
7127 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
7128                        if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
7129                          _e_border_check_stack(bd);
7130 #endif
7131                        bd->client.e.state.rot.pending_show = 0;
7132                     }
7133                }
7134           }
7135      }
7136 #endif
7137    return ECORE_CALLBACK_PASS_ON;
7138 }
7139
7140 static Eina_Bool
7141 _e_border_cb_window_state_request(void *data  __UNUSED__,
7142                                   int ev_type __UNUSED__,
7143                                   void       *ev)
7144 {
7145    E_Border *bd;
7146    Ecore_X_Event_Window_State_Request *e;
7147    int i;
7148
7149    e = ev;
7150    bd = e_border_find_by_client_window(e->win);
7151    if (!bd) return ECORE_CALLBACK_PASS_ON;
7152
7153    for (i = 0; i < 2; i++)
7154      e_hints_window_state_update(bd, e->state[i], e->action);
7155
7156    return ECORE_CALLBACK_PASS_ON;
7157 }
7158
7159 static Eina_Bool
7160 _e_border_cb_window_move_resize_request(void *data  __UNUSED__,
7161                                         int ev_type __UNUSED__,
7162                                         void       *ev)
7163 {
7164    E_Border *bd;
7165    Ecore_X_Event_Window_Move_Resize_Request *e;
7166
7167    e = ev;
7168    bd = e_border_find_by_client_window(e->win);
7169    if (!bd) return ECORE_CALLBACK_PASS_ON;
7170
7171    if ((bd->shaded) || (bd->shading) ||
7172        (bd->fullscreen) || (bd->moving) ||
7173        (bd->resize_mode != RESIZE_NONE))
7174      return ECORE_CALLBACK_PASS_ON;
7175
7176    if ((e->button >= 1) && (e->button <= 3))
7177      {
7178         bd->mouse.last_down[e->button - 1].mx = e->x;
7179         bd->mouse.last_down[e->button - 1].my = e->y;
7180         bd->mouse.last_down[e->button - 1].x = bd->x;
7181         bd->mouse.last_down[e->button - 1].y = bd->y;
7182         bd->mouse.last_down[e->button - 1].w = bd->w;
7183         bd->mouse.last_down[e->button - 1].h = bd->h;
7184      }
7185    else
7186      {
7187         bd->moveinfo.down.x = bd->x;
7188         bd->moveinfo.down.y = bd->y;
7189         bd->moveinfo.down.w = bd->w;
7190         bd->moveinfo.down.h = bd->h;
7191      }
7192    bd->mouse.current.mx = e->x;
7193    bd->mouse.current.my = e->y;
7194    bd->moveinfo.down.button = e->button;
7195    bd->moveinfo.down.mx = e->x;
7196    bd->moveinfo.down.my = e->y;
7197    grabbed = 1;
7198
7199    if (!bd->lock_user_stacking)
7200      e_border_raise(bd);
7201
7202    if (e->direction == MOVE)
7203      {
7204         bd->cur_mouse_action = e_action_find("window_move");
7205         if (bd->cur_mouse_action)
7206           {
7207              if ((!bd->cur_mouse_action->func.end_mouse) &&
7208                  (!bd->cur_mouse_action->func.end))
7209                bd->cur_mouse_action = NULL;
7210              if (bd->cur_mouse_action)
7211                {
7212                   e_object_ref(E_OBJECT(bd->cur_mouse_action));
7213                   bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
7214                }
7215           }
7216         return ECORE_CALLBACK_PASS_ON;
7217      }
7218
7219    if (!_e_border_resize_begin(bd))
7220      return ECORE_CALLBACK_PASS_ON;
7221
7222    switch (e->direction)
7223      {
7224       case RESIZE_TL:
7225         bd->resize_mode = RESIZE_TL;
7226         GRAV_SET(bd, ECORE_X_GRAVITY_SE);
7227         break;
7228
7229       case RESIZE_T:
7230         bd->resize_mode = RESIZE_T;
7231         GRAV_SET(bd, ECORE_X_GRAVITY_S);
7232         break;
7233
7234       case RESIZE_TR:
7235         bd->resize_mode = RESIZE_TR;
7236         GRAV_SET(bd, ECORE_X_GRAVITY_SW);
7237         break;
7238
7239       case RESIZE_R:
7240         bd->resize_mode = RESIZE_R;
7241         GRAV_SET(bd, ECORE_X_GRAVITY_W);
7242         break;
7243
7244       case RESIZE_BR:
7245         bd->resize_mode = RESIZE_BR;
7246         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
7247         break;
7248
7249       case RESIZE_B:
7250         bd->resize_mode = RESIZE_B;
7251         GRAV_SET(bd, ECORE_X_GRAVITY_N);
7252         break;
7253
7254       case RESIZE_BL:
7255         bd->resize_mode = RESIZE_BL;
7256         GRAV_SET(bd, ECORE_X_GRAVITY_NE);
7257         break;
7258
7259       case RESIZE_L:
7260         bd->resize_mode = RESIZE_L;
7261         GRAV_SET(bd, ECORE_X_GRAVITY_E);
7262         break;
7263
7264       default:
7265         return ECORE_CALLBACK_PASS_ON;
7266      }
7267
7268    bd->cur_mouse_action = e_action_find("window_resize");
7269    if (bd->cur_mouse_action)
7270      {
7271         if ((!bd->cur_mouse_action->func.end_mouse) &&
7272             (!bd->cur_mouse_action->func.end))
7273           bd->cur_mouse_action = NULL;
7274      }
7275    if (bd->cur_mouse_action)
7276      e_object_ref(E_OBJECT(bd->cur_mouse_action));
7277
7278    return ECORE_CALLBACK_PASS_ON;
7279 }
7280
7281 static Eina_Bool
7282 _e_border_cb_desktop_change(void *data  __UNUSED__,
7283                             int ev_type __UNUSED__,
7284                             void       *ev)
7285 {
7286    E_Border *bd;
7287    Ecore_X_Event_Desktop_Change *e;
7288
7289    e = ev;
7290    bd = e_border_find_by_client_window(e->win);
7291    if (bd)
7292      {
7293         if (e->desk == 0xffffffff)
7294           e_border_stick(bd);
7295         else if ((int)e->desk < (bd->zone->desk_x_count * bd->zone->desk_y_count))
7296           {
7297              E_Desk *desk;
7298
7299              desk = e_desk_at_pos_get(bd->zone, e->desk);
7300              if (desk)
7301                e_border_desk_set(bd, desk);
7302           }
7303      }
7304    else
7305      {
7306         ecore_x_netwm_desktop_set(e->win, e->desk);
7307      }
7308    return ECORE_CALLBACK_PASS_ON;
7309 }
7310
7311 static Eina_Bool
7312 _e_border_cb_sync_alarm(void *data  __UNUSED__,
7313                         int ev_type __UNUSED__,
7314                         void       *ev)
7315 {
7316    E_Border *bd;
7317    Ecore_X_Event_Sync_Alarm *e;
7318    unsigned int serial;
7319
7320    e = ev;
7321    bd = e_border_find_by_alarm(e->alarm);
7322    if (!bd) return ECORE_CALLBACK_PASS_ON;
7323
7324    if (bd->client.netwm.sync.wait)
7325      bd->client.netwm.sync.wait--;
7326
7327    if (ecore_x_sync_counter_query(bd->client.netwm.sync.counter, &serial))
7328      {
7329         E_Border_Pending_Move_Resize *pnd = NULL;
7330
7331         /* skip pending for which we didn't get a reply */
7332         while (bd->pending_move_resize)
7333           {
7334              pnd = bd->pending_move_resize->data;
7335              bd->pending_move_resize = eina_list_remove(bd->pending_move_resize, pnd);
7336
7337              if (serial == pnd->serial)
7338                break;
7339
7340              E_FREE(pnd);
7341           }
7342
7343         if (pnd)
7344           {
7345              bd->x = pnd->x;
7346              bd->y = pnd->y;
7347              bd->w = pnd->w;
7348              bd->h = pnd->h;
7349              bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
7350              bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
7351              E_FREE(pnd);
7352           }
7353      }
7354
7355    bd->changes.size = 1;
7356    bd->changes.pos = 1;
7357
7358    _e_border_eval(bd);
7359    evas_render(bd->bg_evas);
7360
7361    ecore_x_pointer_xy_get(e_manager_current_get()->root,
7362                           &bd->mouse.current.mx,
7363                           &bd->mouse.current.my);
7364
7365    bd->client.netwm.sync.send_time = ecore_loop_time_get();
7366    _e_border_resize_handle(bd);
7367
7368    return ECORE_CALLBACK_PASS_ON;
7369 }
7370
7371 static Eina_Bool
7372 _e_border_cb_efreet_cache_update(void *data  __UNUSED__,
7373                                  int ev_type __UNUSED__,
7374                                  void *ev    __UNUSED__)
7375 {
7376    Eina_List *l;
7377    E_Border *bd;
7378
7379    /* mark all borders for desktop/icon updates */
7380    EINA_LIST_FOREACH(borders, l, bd)
7381      {
7382         if (bd->desktop)
7383           {
7384              efreet_desktop_free(bd->desktop);
7385              bd->desktop = NULL;
7386           }
7387         bd->changes.icon = 1;
7388         bd->changed = 1;
7389      }
7390    /*
7391       e_init_status_set(_("Desktop files scan done"));
7392       e_init_done();
7393     */
7394    return ECORE_CALLBACK_PASS_ON;
7395 }
7396
7397 static Eina_Bool
7398 _e_border_cb_config_icon_theme(void *data  __UNUSED__,
7399                                int ev_type __UNUSED__,
7400                                void *ev    __UNUSED__)
7401 {
7402    Eina_List *l;
7403    E_Border *bd;
7404
7405    /* mark all borders for desktop/icon updates */
7406    EINA_LIST_FOREACH(borders, l, bd)
7407      {
7408         bd->changes.icon = 1;
7409         bd->changed = 1;
7410      }
7411    return ECORE_CALLBACK_PASS_ON;
7412 }
7413
7414 static Eina_Bool
7415 _e_border_cb_pointer_warp(void *data  __UNUSED__,
7416                           int ev_type __UNUSED__,
7417                           void       *ev)
7418 {
7419    E_Event_Pointer_Warp *e;
7420
7421    e = ev;
7422    if (!bdmove) return ECORE_CALLBACK_PASS_ON;
7423    e_border_move(bdmove, bdmove->x + (e->curr.x - e->prev.x), bdmove->y + (e->curr.y - e->prev.y));
7424    return ECORE_CALLBACK_PASS_ON;
7425 }
7426
7427 static void
7428 _e_border_cb_signal_bind(void            *data,
7429                          Evas_Object *obj __UNUSED__,
7430                          const char      *emission,
7431                          const char      *source)
7432 {
7433    E_Border *bd;
7434
7435    bd = data;
7436    if (e_dnd_active()) return;
7437    e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd),
7438                             emission, source);
7439 }
7440
7441 static Eina_Bool
7442 _e_border_cb_mouse_in(void    *data,
7443                       int type __UNUSED__,
7444                       void    *event)
7445 {
7446    Ecore_X_Event_Mouse_In *ev;
7447    E_Border *bd;
7448
7449    ev = event;
7450    bd = data;
7451 #ifdef INOUTDEBUG_MOUSE
7452    {
7453       time_t t;
7454       char *ct;
7455
7456       const char *modes[] = {
7457          "MODE_NORMAL",
7458          "MODE_WHILE_GRABBED",
7459          "MODE_GRAB",
7460          "MODE_UNGRAB"
7461       };
7462       const char *details[] = {
7463          "DETAIL_ANCESTOR",
7464          "DETAIL_VIRTUAL",
7465          "DETAIL_INFERIOR",
7466          "DETAIL_NON_LINEAR",
7467          "DETAIL_NON_LINEAR_VIRTUAL",
7468          "DETAIL_POINTER",
7469          "DETAIL_POINTER_ROOT",
7470          "DETAIL_DETAIL_NONE"
7471       };
7472       t = time(NULL);
7473       ct = ctime(&t);
7474       ct[strlen(ct) - 1] = 0;
7475       DBG("@@ ->IN 0x%x 0x%x %s md=%s dt=%s",
7476              ev->win, ev->event_win,
7477              ct,
7478              modes[ev->mode],
7479              details[ev->detail]);
7480    }
7481 #endif
7482    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7483    if (ev->event_win == bd->win)
7484      {
7485         e_focus_event_mouse_in(bd);
7486      }
7487 #if 0
7488    if ((ev->win != bd->win) &&
7489        (ev->win != bd->event_win) &&
7490        (ev->event_win != bd->win) &&
7491        (ev->event_win != bd->event_win))
7492      return ECORE_CALLBACK_PASS_ON;
7493 #else
7494    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7495 #endif
7496    bd->mouse.current.mx = ev->root.x;
7497    bd->mouse.current.my = ev->root.y;
7498    if (!bd->bg_evas_in)
7499      {
7500         evas_event_feed_mouse_in(bd->bg_evas, ev->time, NULL);
7501         bd->bg_evas_in = EINA_TRUE;
7502      }
7503    return ECORE_CALLBACK_PASS_ON;
7504 }
7505
7506 static Eina_Bool
7507 _e_border_cb_mouse_out(void    *data,
7508                        int type __UNUSED__,
7509                        void    *event)
7510 {
7511    Ecore_X_Event_Mouse_Out *ev;
7512    E_Border *bd;
7513
7514    ev = event;
7515    bd = data;
7516 #ifdef INOUTDEBUG_MOUSE
7517    {
7518       time_t t;
7519       char *ct;
7520
7521       const char *modes[] = {
7522          "MODE_NORMAL",
7523          "MODE_WHILE_GRABBED",
7524          "MODE_GRAB",
7525          "MODE_UNGRAB"
7526       };
7527       const char *details[] = {
7528          "DETAIL_ANCESTOR",
7529          "DETAIL_VIRTUAL",
7530          "DETAIL_INFERIOR",
7531          "DETAIL_NON_LINEAR",
7532          "DETAIL_NON_LINEAR_VIRTUAL",
7533          "DETAIL_POINTER",
7534          "DETAIL_POINTER_ROOT",
7535          "DETAIL_DETAIL_NONE"
7536       };
7537       t = time(NULL);
7538       ct = ctime(&t);
7539       ct[strlen(ct) - 1] = 0;
7540       DBG("@@ <-OUT 0x%x 0x%x %s md=%s dt=%s",
7541              ev->win, ev->event_win,
7542              ct,
7543              modes[ev->mode],
7544              details[ev->detail]);
7545    }
7546 #endif
7547    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7548    if (ev->event_win == bd->win)
7549      {
7550         if (bd->fullscreen)
7551           return ECORE_CALLBACK_PASS_ON;
7552         if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
7553             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7554           return ECORE_CALLBACK_PASS_ON;
7555         if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7556           return ECORE_CALLBACK_PASS_ON;
7557         if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
7558             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7559           return ECORE_CALLBACK_PASS_ON;
7560         e_focus_event_mouse_out(bd);
7561      }
7562 #if 0
7563    if ((ev->win != bd->win) &&
7564        (ev->win != bd->event_win) &&
7565        (ev->event_win != bd->win) &&
7566        (ev->event_win != bd->event_win))
7567      return ECORE_CALLBACK_PASS_ON;
7568 #else
7569    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7570 #endif
7571    bd->mouse.current.mx = ev->root.x;
7572    bd->mouse.current.my = ev->root.y;
7573    if (bd->bg_evas_in)
7574      {
7575         if (!((evas_event_down_count_get(bd->bg_evas) > 0) &&
7576               (!((ev->mode == ECORE_X_EVENT_MODE_GRAB) &&
7577                  (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)))))
7578           {
7579              if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7580                evas_event_feed_mouse_cancel(bd->bg_evas, ev->time, NULL);
7581              evas_event_feed_mouse_out(bd->bg_evas, ev->time, NULL);
7582              bd->bg_evas_in = EINA_FALSE;
7583           }
7584      }
7585    return ECORE_CALLBACK_PASS_ON;
7586 }
7587
7588 static Eina_Bool
7589 _e_border_cb_mouse_wheel(void    *data,
7590                          int type __UNUSED__,
7591                          void    *event)
7592 {
7593    Ecore_Event_Mouse_Wheel *ev;
7594    E_Border *bd;
7595
7596    ev = event;
7597    bd = data;
7598    if ((ev->event_window == bd->win) ||
7599        (ev->event_window == bd->event_win))
7600      {
7601         bd->mouse.current.mx = ev->root.x;
7602         bd->mouse.current.my = ev->root.y;
7603         if (!bd->cur_mouse_action)
7604           e_bindings_wheel_event_handle(E_BINDING_CONTEXT_WINDOW,
7605                                         E_OBJECT(bd), ev);
7606      }
7607    evas_event_feed_mouse_wheel(bd->bg_evas, ev->direction, ev->z, ev->timestamp, NULL);
7608    return ECORE_CALLBACK_PASS_ON;
7609 }
7610
7611 static Eina_Bool
7612 _e_border_cb_mouse_down(void    *data,
7613                         int type __UNUSED__,
7614                         void    *event)
7615 {
7616    Ecore_Event_Mouse_Button *ev;
7617    E_Border *bd;
7618
7619    ev = event;
7620    bd = data;
7621    if ((ev->event_window == bd->win) ||
7622        (ev->event_window == bd->event_win))
7623      {
7624         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7625           {
7626              bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7627              bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7628              bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7629              bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7630              bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7631              bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7632           }
7633         else
7634           {
7635              bd->moveinfo.down.x = bd->x + bd->fx.x;
7636              bd->moveinfo.down.y = bd->y + bd->fx.y;
7637              bd->moveinfo.down.w = bd->w;
7638              bd->moveinfo.down.h = bd->h;
7639           }
7640         bd->mouse.current.mx = ev->root.x;
7641         bd->mouse.current.my = ev->root.y;
7642         if (!bd->cur_mouse_action)
7643           {
7644              bd->cur_mouse_action =
7645                e_bindings_mouse_down_event_handle(E_BINDING_CONTEXT_WINDOW,
7646                                                   E_OBJECT(bd), ev);
7647              if (bd->cur_mouse_action)
7648                {
7649                   if ((!bd->cur_mouse_action->func.end_mouse) &&
7650                       (!bd->cur_mouse_action->func.end))
7651                     bd->cur_mouse_action = NULL;
7652                   if (bd->cur_mouse_action)
7653                     e_object_ref(E_OBJECT(bd->cur_mouse_action));
7654                }
7655           }
7656         e_focus_event_mouse_down(bd);
7657      }
7658    if (ev->window != ev->event_window)
7659      {
7660         return 1;
7661      }
7662    if ((ev->window != bd->event_win) && (ev->event_window != bd->win))
7663      {
7664         return 1;
7665      }
7666    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7667      {
7668         bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7669         bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7670         bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7671         bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7672         bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7673         bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7674      }
7675    else
7676      {
7677         bd->moveinfo.down.x = bd->x + bd->fx.x;
7678         bd->moveinfo.down.y = bd->y + bd->fx.y;
7679         bd->moveinfo.down.w = bd->w;
7680         bd->moveinfo.down.h = bd->h;
7681      }
7682    bd->mouse.current.mx = ev->root.x;
7683    bd->mouse.current.my = ev->root.y;
7684 /*
7685    if (bd->moving)
7686      {
7687      }
7688    else if (bd->resize_mode != RESIZE_NONE)
7689      {
7690      }
7691    else
7692  */
7693    {
7694       Evas_Button_Flags flags = EVAS_BUTTON_NONE;
7695
7696       if (ev->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
7697       if (ev->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
7698       evas_event_feed_mouse_down(bd->bg_evas, ev->buttons, flags, ev->timestamp, NULL);
7699    }
7700    return ECORE_CALLBACK_PASS_ON;
7701 }
7702
7703 static Eina_Bool
7704 _e_border_cb_mouse_up(void    *data,
7705                       int type __UNUSED__,
7706                       void    *event)
7707 {
7708    Ecore_Event_Mouse_Button *ev;
7709    E_Border *bd;
7710
7711    ev = event;
7712    bd = data;
7713    if ((ev->event_window == bd->win) ||
7714        (ev->event_window == bd->event_win))
7715      {
7716         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7717           {
7718              bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7719              bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7720              bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7721              bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7722           }
7723         bd->mouse.current.mx = ev->root.x;
7724         bd->mouse.current.my = ev->root.y;
7725         /* also we dont pass the same params that went in - then again that */
7726         /* should be ok as we are just ending the action if it has an end */
7727         if (bd->cur_mouse_action)
7728           {
7729              if (bd->cur_mouse_action->func.end_mouse)
7730                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", ev);
7731              else if (bd->cur_mouse_action->func.end)
7732                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
7733              e_object_unref(E_OBJECT(bd->cur_mouse_action));
7734              bd->cur_mouse_action = NULL;
7735           }
7736         else
7737           {
7738              if (!e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd), ev))
7739                e_focus_event_mouse_up(bd);
7740           }
7741      }
7742    if (ev->window != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7743    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7744      {
7745         bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7746         bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7747         bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7748         bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7749      }
7750    bd->mouse.current.mx = ev->root.x;
7751    bd->mouse.current.my = ev->root.y;
7752
7753    bd->drag.start = 0;
7754
7755    evas_event_feed_mouse_up(bd->bg_evas, ev->buttons, EVAS_BUTTON_NONE, ev->timestamp, NULL);
7756    return ECORE_CALLBACK_PASS_ON;
7757 }
7758
7759 static void
7760 _e_border_stay_within_container(E_Border *bd, int x, int y, int *new_x, int *new_y)
7761 {
7762 #ifdef _F_BORDER_CLIP_TO_ZONE_
7763    int new_x_max, new_y_max;
7764    int new_x_min, new_y_min;
7765    int margin_x, margin_y;
7766
7767    margin_x = bd->w - 100;
7768    margin_y = bd->h - 100;
7769
7770    new_x_max = bd->zone->x + bd->zone->w - bd->w + margin_x;
7771    new_x_min = bd->zone->x - margin_x;
7772    new_y_max = bd->zone->y + bd->zone->h - bd->h + margin_y;
7773    new_y_min = bd->zone->y - margin_y;
7774
7775    if (x >= new_x_max)      *new_x = new_x_max;
7776    else if (x <= new_x_min) *new_x = new_x_min;
7777
7778    if (y >= new_y_max)      *new_y = new_y_max;
7779    else if (y <= new_y_min) *new_y = new_y_min;
7780 #endif
7781 }
7782
7783 static Eina_Bool
7784 _e_border_cb_mouse_move(void    *data,
7785                         int type __UNUSED__,
7786                         void    *event)
7787 {
7788    Ecore_Event_Mouse_Move *ev;
7789    E_Border *bd;
7790
7791    ev = event;
7792    bd = data;
7793    if ((ev->window != bd->event_win) &&
7794        (ev->event_window != bd->win)) return ECORE_CALLBACK_PASS_ON;
7795    bd->mouse.current.mx = ev->root.x;
7796    bd->mouse.current.my = ev->root.y;
7797    if (bd->moving)
7798      {
7799         int x, y, new_x, new_y;
7800         int new_w, new_h;
7801         Eina_List *skiplist = NULL;
7802 #if 0
7803         // FIXME: remove? sync what for when only moving?
7804         if ((ecore_loop_time_get() - bd->client.netwm.sync.time) > 0.5)
7805           bd->client.netwm.sync.wait = 0;
7806         if ((bd->client.netwm.sync.request) &&
7807             (bd->client.netwm.sync.alarm) &&
7808             (bd->client.netwm.sync.wait > 1)) return ECORE_CALLBACK_PASS_ON;
7809 #endif
7810         if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
7811           {
7812              x = bd->mouse.last_down[bd->moveinfo.down.button - 1].x +
7813                (bd->mouse.current.mx - bd->moveinfo.down.mx);
7814              y = bd->mouse.last_down[bd->moveinfo.down.button - 1].y +
7815                (bd->mouse.current.my - bd->moveinfo.down.my);
7816           }
7817         else
7818           {
7819              x = bd->moveinfo.down.x +
7820                (bd->mouse.current.mx - bd->moveinfo.down.mx);
7821              y = bd->moveinfo.down.y +
7822                (bd->mouse.current.my - bd->moveinfo.down.my);
7823           }
7824         new_x = x;
7825         new_y = y;
7826
7827 #ifdef _F_USE_RESIST_MAGNETIC_EFFECT_
7828         skiplist = eina_list_append(skiplist, bd);
7829         e_resist_container_border_position(bd->zone->container, skiplist,
7830                                            bd->x, bd->y, bd->w, bd->h,
7831                                            x, y, bd->w, bd->h,
7832                                            &new_x, &new_y, &new_w, &new_h);
7833         eina_list_free(skiplist);
7834
7835         _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
7836 #else
7837         /* if (e_config->window_out_of_vscreen_limits_partly) */
7838         if (1)
7839           _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
7840         else
7841           {
7842              skiplist = eina_list_append(skiplist, bd);
7843              e_resist_container_border_position(bd->zone->container, skiplist,
7844                                                 bd->x, bd->y, bd->w, bd->h,
7845                                                 x, y, bd->w, bd->h,
7846                                                 &new_x, &new_y, &new_w, &new_h);
7847              eina_list_free(skiplist);
7848           }
7849 #endif
7850         bd->shelf_fix.x = 0;
7851         bd->shelf_fix.y = 0;
7852         bd->shelf_fix.modified = 0;
7853         e_border_move(bd, new_x, new_y);
7854         e_zone_flip_coords_handle(bd->zone, ev->root.x, ev->root.y);
7855      }
7856    else if (bd->resize_mode != RESIZE_NONE)
7857      {
7858         if ((bd->client.netwm.sync.request) &&
7859             (bd->client.netwm.sync.alarm))
7860           {
7861              if ((ecore_loop_time_get() - bd->client.netwm.sync.send_time) > 0.5)
7862                {
7863                   E_Border_Pending_Move_Resize *pnd;
7864
7865                   if (bd->pending_move_resize)
7866                     {
7867                        bd->changes.pos = 1;
7868                        bd->changes.size = 1;
7869                        bd->changed = 1;
7870                        _e_border_client_move_resize_send(bd);
7871                     }
7872                   EINA_LIST_FREE(bd->pending_move_resize, pnd)
7873                     E_FREE(pnd);
7874
7875                   bd->client.netwm.sync.wait = 0;
7876                }
7877              /* sync.wait is incremented when resize_handle sends
7878               * sync-request and decremented by sync-alarm cb. so
7879               * we resize here either on initial resize, timeout or
7880               * when no new resize-request was added by sync-alarm cb.
7881               */
7882              if (!bd->client.netwm.sync.wait)
7883                _e_border_resize_handle(bd);
7884           }
7885         else
7886           _e_border_resize_handle(bd);
7887      }
7888    else
7889      {
7890         if (bd->drag.start)
7891           {
7892              if ((bd->drag.x == -1) && (bd->drag.y == -1))
7893                {
7894                   bd->drag.x = ev->root.x;
7895                   bd->drag.y = ev->root.y;
7896                }
7897              else
7898                {
7899                   int dx, dy;
7900
7901                   dx = bd->drag.x - ev->root.x;
7902                   dy = bd->drag.y - ev->root.y;
7903                   if (((dx * dx) + (dy * dy)) >
7904                       (e_config->drag_resist * e_config->drag_resist))
7905                     {
7906      /* start drag! */
7907                         if (bd->icon_object)
7908                           {
7909                              Evas_Object *o = NULL;
7910                              Evas_Coord x, y, w, h;
7911                              const char *drag_types[] = { "enlightenment/border" };
7912
7913                              e_object_ref(E_OBJECT(bd));
7914                              evas_object_geometry_get(bd->icon_object,
7915                                                       &x, &y, &w, &h);
7916                              drag_border = e_drag_new(bd->zone->container,
7917                                                       bd->x + bd->fx.x + x,
7918                                                       bd->y + bd->fx.y + y,
7919                                                       drag_types, 1, bd, -1,
7920                                                       NULL,
7921                                                       _e_border_cb_drag_finished);
7922                              o = e_border_icon_add(bd, drag_border->evas);
7923                              if (!o)
7924                                {
7925      /* FIXME: fallback icon for drag */
7926                                    o = evas_object_rectangle_add(drag_border->evas);
7927                                    evas_object_color_set(o, 255, 255, 255, 255);
7928                                }
7929                              e_drag_object_set(drag_border, o);
7930
7931                              e_drag_resize(drag_border, w, h);
7932                              e_drag_start(drag_border, bd->drag.x, bd->drag.y);
7933                           }
7934                         bd->drag.start = 0;
7935                     }
7936                }
7937           }
7938         evas_event_feed_mouse_move(bd->bg_evas, ev->x, ev->y, ev->timestamp, NULL);
7939      }
7940    return ECORE_CALLBACK_PASS_ON;
7941 }
7942
7943 static Eina_Bool
7944 _e_border_cb_grab_replay(void *data __UNUSED__,
7945                          int        type,
7946                          void      *event)
7947 {
7948    Ecore_Event_Mouse_Button *ev;
7949
7950    if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
7951    ev = event;
7952    if ((e_config->pass_click_on)
7953        || (e_config->always_click_to_raise) // this works even if not on click-to-focus
7954        || (e_config->always_click_to_focus) // this works even if not on click-to-focus
7955       )
7956      {
7957         E_Border *bd;
7958
7959         bd = e_border_find_by_window(ev->event_window);
7960         if (bd)
7961           {
7962              if (bd->cur_mouse_action)
7963                return ECORE_CALLBACK_DONE;
7964              if (ev->event_window == bd->win)
7965                {
7966                   if (!e_bindings_mouse_down_find(E_BINDING_CONTEXT_WINDOW,
7967                                                   E_OBJECT(bd), ev, NULL))
7968                     return ECORE_CALLBACK_PASS_ON;
7969                }
7970           }
7971      }
7972    return ECORE_CALLBACK_DONE;
7973 }
7974
7975 static void
7976 _e_border_cb_drag_finished(E_Drag     *drag,
7977                            int dropped __UNUSED__)
7978 {
7979    E_Border *bd;
7980
7981    bd = drag->data;
7982    e_object_unref(E_OBJECT(bd));
7983    drag_border = NULL;
7984 }
7985
7986 #ifdef _F_USE_DESK_WINDOW_PROFILE_
7987 static Eina_Bool
7988 _e_border_cb_desk_window_profile_change(void *data  __UNUSED__,
7989                                         int ev_type __UNUSED__,
7990                                         void       *ev)
7991 {
7992    E_Event_Desk_Window_Profile_Change *e;
7993    Eina_List *l;
7994    E_Border *bd;
7995
7996    e = ev;
7997    EINA_LIST_FOREACH(borders, l, bd)
7998      {
7999         if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
8000           {
8001              bd->client.e.fetch.profile_list = 1;
8002              bd->changed = 1;
8003           }
8004      }
8005    return ECORE_CALLBACK_PASS_ON;
8006 }
8007 #endif
8008
8009 #ifdef _F_ZONE_WINDOW_ROTATION_
8010 static Eina_Bool
8011 _e_border_cb_zone_rotation_change_begin(void *data  __UNUSED__,
8012                                         int ev_type __UNUSED__,
8013                                         void       *ev)
8014 {
8015    E_Event_Zone_Rotation_Change_Begin *e = ev;
8016
8017    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8018    if ((!e) || (!e->zone)) return ECORE_CALLBACK_PASS_ON;
8019
8020    if (!_e_border_rotation_zone_set(e->zone))
8021      {
8022         /* there is no border which supports window manager rotation */
8023         e_zone_rotation_update_cancel(e->zone);
8024      }
8025    return ECORE_CALLBACK_PASS_ON;
8026 }
8027
8028 static void
8029 _e_border_cb_rotation_sync_job(void *data)
8030 {
8031    E_Zone *zone = data;
8032    Eina_List *l;
8033    E_Border_Rotation_Info *info = NULL;
8034
8035    ELB(ELBT_ROT, "DO ROTATION SYNC_JOB", zone->id);
8036
8037    if (rot.list)
8038      {
8039         EINA_LIST_FOREACH(rot.list, l, info)
8040            _e_border_hook_call(E_BORDER_HOOK_ROTATION_LIST_ADD, info->bd);
8041         if (!rot.wait_prepare_done)
8042           {
8043              _e_border_rotation_change_request(zone);
8044           }
8045      }
8046
8047    // clear job
8048    if (rot.sync_job)
8049      {
8050         ELB(ELBT_ROT, "DEL SYNC_JOB", zone->id);
8051         ecore_job_del(rot.sync_job);
8052         rot.sync_job = NULL;
8053      }
8054 }
8055
8056 static void
8057 _e_border_cb_rotation_async_job(void *data)
8058 {
8059    E_Zone *zone = data;
8060
8061    if (rot.list) goto end;
8062
8063    ELB(ELBT_ROT, "FLUSH ASYNC LIST TO ROT_CHANGE_REQ", zone->id);
8064
8065    _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8066    rot.async_list = NULL;
8067
8068 end:
8069    // clear async job
8070    if (rot.async_job)
8071      {
8072         ELB(ELBT_ROT, "DEL ASYNC_JOB", zone->id);
8073         ecore_job_del(rot.async_job);
8074         rot.async_job = NULL;
8075      }
8076 }
8077
8078 static Eina_Bool
8079 _e_border_rotation_change_prepare_timeout(void *data)
8080 {
8081    E_Zone *zone = data;
8082    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8083
8084    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE_PREPARE", 0);
8085
8086    if ((zone) && (rot.wait_prepare_done))
8087      {
8088         if (rot.list)
8089           {
8090              _e_border_rotation_change_request(zone);
8091              if (rot.prepare_timer)
8092                ecore_timer_del(rot.prepare_timer);
8093              rot.prepare_timer = NULL;
8094              rot.wait_prepare_done = EINA_FALSE;
8095           }
8096      }
8097    return ECORE_CALLBACK_CANCEL;
8098 }
8099
8100 static void
8101 _e_border_rotation_change_request(E_Zone *zone)
8102 {
8103    if (!e_config->wm_win_rotation) return;
8104    if (!rot.list) return;
8105    if (eina_list_count(rot.list) <= 0) return;
8106    if (zone->rot.block_count) return;
8107
8108    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8109    rot.prepare_timer = NULL;
8110    rot.wait_prepare_done = EINA_FALSE;
8111
8112    _e_border_rotation_list_flush(rot.list, EINA_FALSE);
8113
8114    if (rot.done_timer)
8115      ecore_timer_del(rot.done_timer);
8116    ELB(ELBT_ROT, "ADD TIMEOUT ROT_DONE", zone->id);
8117    rot.done_timer = ecore_timer_add(5.0f,
8118                                     _e_border_rotation_change_done_timeout,
8119                                     NULL);
8120 }
8121
8122 static void
8123 _e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush)
8124 {
8125    Eina_List *l;
8126    E_Border_Rotation_Info *info =NULL;
8127    int x, y, w, h;
8128
8129    EINA_LIST_FOREACH (list, l, info)
8130      {
8131         if (!info->bd) continue;
8132         if ((info->bd->client.e.state.rot.wait_for_done) &&
8133             (info->bd->client.e.state.rot.wait_done_ang == info->ang)) continue;
8134
8135         _e_border_event_border_rotation_change_begin_send(info->bd);
8136
8137         /* resize border */
8138         info->win_resize = _e_border_rotation_pre_resize(info->bd, info->ang, &x, &y, &w, &h);
8139         info->bd->client.e.state.rot.pending_change_request = info->win_resize;
8140
8141         info->x = x; info->y = y;
8142         info->w = w; info->h = h;
8143
8144         ELBF(ELBT_ROT, 1, info->bd->client.win,
8145              "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
8146              info->ang, info->win_resize, info->w, info->h);
8147
8148         ecore_x_e_window_rotation_change_prepare_send
8149            (info->bd->client.win, info->ang,
8150             info->win_resize, info->w, info->h);
8151
8152         if (!info->bd->client.e.state.rot.pending_change_request)
8153           {
8154              ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
8155              ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
8156                                                            info->ang);
8157              info->bd->client.e.state.rot.wait_for_done = 1;
8158              info->bd->client.e.state.rot.wait_done_ang = info->ang;
8159           }
8160      }
8161
8162    if (flush)
8163      {
8164         EINA_LIST_FREE(list, info)
8165            E_FREE(info);
8166      }
8167 }
8168
8169 EAPI void
8170 e_border_rotation_list_clear(E_Zone *zone, Eina_Bool send_request)
8171 {
8172    E_Border_Rotation_Info *info = NULL;
8173
8174    if (send_request) _e_border_rotation_change_request(zone);
8175    else
8176      {
8177         EINA_LIST_FREE(rot.list, info)
8178            E_FREE(info);
8179         rot.list = NULL;
8180      }
8181 }
8182
8183 static void
8184 _e_border_rotation_list_remove(E_Border *bd)
8185 {
8186    Eina_List *l = NULL;
8187    E_Border_Rotation_Info *info = NULL;
8188    E_Event_Border_Rotation_Change_End *ev = NULL;
8189    Eina_Bool found = EINA_FALSE;
8190
8191    if (!e_config->wm_win_rotation) return;
8192
8193    EINA_LIST_FOREACH(rot.list, l, info)
8194      {
8195         if (info->bd == bd)
8196           {
8197              rot.list = eina_list_remove(rot.list, info);
8198              E_FREE(info);
8199              found = EINA_TRUE;
8200           }
8201      }
8202
8203    if (bd->client.e.state.rot.wait_for_done)
8204      {
8205         bd->client.e.state.rot.wait_for_done = 0;
8206
8207         /* if we make the border event in the _e_border_free function,
8208          * then we may meet a crash problem, only work this at least e_border_hide.
8209          */
8210         if (!e_object_is_del(E_OBJECT(bd)))
8211           {
8212              ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
8213              if (ev)
8214                {
8215                   ev->border = bd;
8216                   e_object_ref(E_OBJECT(bd));
8217                   ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_END,
8218                                   ev,
8219                                   _e_border_event_border_rotation_change_end_free,
8220                                   NULL);
8221                }
8222           }
8223
8224         if ((found) &&
8225             (eina_list_count(rot.list) == 0))
8226           {
8227              _e_border_rotation_change_done();
8228           }
8229      }
8230 }
8231
8232 static Eina_Bool
8233 _e_border_rotation_change_done_timeout(void *data __UNUSED__)
8234 {
8235    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8236    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE", 0);
8237    _e_border_rotation_change_done();
8238    return ECORE_CALLBACK_CANCEL;
8239 }
8240
8241 static void
8242 _e_border_rotation_change_done(void)
8243 {
8244    E_Manager *m = NULL;
8245    E_Border_Rotation_Info *info = NULL;
8246
8247    if (!e_config->wm_win_rotation) return;
8248
8249    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8250    rot.prepare_timer = NULL;
8251
8252    rot.wait_prepare_done = EINA_FALSE;
8253
8254    if (rot.done_timer) ecore_timer_del(rot.done_timer);
8255    rot.done_timer = NULL;
8256
8257    EINA_LIST_FREE(rot.list, info)
8258      {
8259         if (info->bd)
8260           {
8261              ELB(ELBT_ROT, "TIMEOUT ROT_DONE", info->bd->client.win);
8262              if (info->bd->client.e.state.rot.pending_show)
8263                {
8264                   ELB(ELBT_ROT, "SHOW PEND(TIMEOUT)", info->bd->client.win);
8265                   e_border_show(info->bd);
8266 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
8267                   if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
8268                     _e_border_check_stack(info->bd);
8269 #endif
8270                   info->bd->client.e.state.rot.pending_show = 0;
8271                }
8272              info->bd->client.e.state.rot.wait_for_done = 0;
8273           }
8274         E_FREE(info);
8275      }
8276
8277    _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8278
8279    rot.list = NULL;
8280    rot.async_list = NULL;
8281
8282    m = e_manager_current_get();
8283    e_manager_comp_screen_unlock(m);
8284    e_zone_rotation_update_done(e_util_zone_current_get(m));
8285 }
8286
8287 static int
8288 _prev_angle_get(Ecore_X_Window win)
8289 {
8290    int ret, count = 0, ang = -1;
8291    unsigned char* data = NULL;
8292
8293    ret = ecore_x_window_prop_property_get
8294       (win, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
8295       ECORE_X_ATOM_CARDINAL, 32, &data, &count);
8296
8297    if ((ret) && (data) && (count))
8298      ang = ((int *)data)[0];
8299    if (data) free(data);
8300    return ang;
8301 }
8302
8303 /* get proper rotation value using preferred rotation and list of available rotations */
8304 static int
8305 _e_border_rotation_get(E_Border *bd,
8306                        int       base_ang)
8307 {
8308    int ang = -1;
8309    int current_ang = bd->client.e.state.rot.curr;
8310    unsigned int i;
8311    Eina_Bool found = EINA_FALSE;
8312    Eina_Bool found_curr_ang = EINA_FALSE;
8313
8314    if (!e_config->wm_win_rotation) return ang;
8315    if (!bd->client.e.state.rot.app_set) return ang;
8316
8317    if (bd->client.e.state.rot.preferred_rot != -1)
8318      {
8319         ang = bd->client.e.state.rot.preferred_rot;
8320         ELBF(ELBT_ROT, 0, bd->client.win, "ang:%d base_ang:%d", ang, base_ang);
8321      }
8322    else if ((bd->client.e.state.rot.available_rots) &&
8323             (bd->client.e.state.rot.count))
8324      {
8325         for (i = 0; i < bd->client.e.state.rot.count; i++)
8326           {
8327              if (bd->client.e.state.rot.available_rots[i] == base_ang)
8328                {
8329                   ang = base_ang;
8330                   found = EINA_TRUE;
8331                   break;
8332                }
8333              if (bd->client.e.state.rot.available_rots[i] == current_ang)
8334                found_curr_ang = EINA_TRUE;
8335           }
8336
8337         /* do nothing. this window wants to maintain current state.
8338          * for example, window's available_rots: 0, 90, 270,
8339          * current zone rotation request: 180. the WM does nothing
8340          * for this window.
8341          */
8342         if (!found)
8343           {
8344              if ((bd->client.e.state.rot.curr != -1) && (found_curr_ang))
8345                ang = bd->client.e.state.rot.curr;
8346              else
8347                ang = bd->client.e.state.rot.available_rots[0];
8348           }
8349      }
8350    else
8351      {
8352         /* In this case, border doesn't have a list of
8353          * available rotations, thus WM should request
8354          * rotation with '0' degree to the application.
8355          */
8356         ang = 0;
8357      }
8358
8359    return ang;
8360 }
8361
8362 static int
8363 _e_border_rotation_angle_get(E_Border *bd)
8364 {
8365    E_Zone *zone = bd->zone;
8366    int will_ang = 0;
8367    int _ang = 0;
8368    int ret = -1;
8369
8370    if (!e_config->wm_win_rotation) return ret;
8371    if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) return ret;
8372
8373    ELB(ELBT_ROT, "CHECK ROT", bd->client.win);
8374
8375    // the window with "ECORE_X_WINDOW_TYPE_NORMAL" type
8376    // should follow the state of rotation of zone.
8377    if ((bd->parent) &&
8378        (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL))
8379      will_ang = bd->parent->client.e.state.rot.curr;
8380    else will_ang = zone->rot.curr;
8381
8382    if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
8383      {
8384         ELBF(ELBT_ROT, 1, bd->client.win,
8385              "%s->parent:0x%08x (support:%d app_set:%d ang:%d)",
8386              (rot.vkbd == bd) ? "vkbd" : "prediction",
8387              bd->parent ? bd->parent->client.win : 0,
8388              bd->parent ? bd->parent->client.e.state.rot.support : -1,
8389              bd->parent ? bd->parent->client.e.state.rot.app_set : -1,
8390              bd->parent ? bd->parent->client.e.state.rot.curr : -1);
8391
8392         if (bd->parent)
8393           {
8394              will_ang = bd->parent->client.e.state.rot.curr;
8395              if ((!bd->parent->client.e.state.rot.support) &&
8396                  (!bd->parent->client.e.state.rot.app_set))
8397                {
8398                   will_ang = 0;
8399                }
8400           }
8401      }
8402
8403    if ((!bd->client.e.state.rot.app_set) &&
8404        (!bd->client.e.state.rot.support))
8405      {
8406         /* hack for magnifier and keyboard popup */
8407         if ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER) ||
8408             (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP))
8409           {
8410              ELB(ELBT_BD, "MAG", bd->client.win);
8411              will_ang = 0;
8412              if ((rot.vkbd) && (rot.vkbd->visible))
8413                will_ang = rot.vkbd->client.e.state.rot.curr;
8414           }
8415      }
8416
8417    if (bd->client.e.state.rot.app_set)
8418      {
8419         /* utility type window should be rotated according to
8420          * rotation of the transient_for window.
8421          */
8422         if ((bd->parent) &&
8423             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
8424           {
8425              will_ang = bd->parent->client.e.state.rot.curr;
8426              if ((!bd->parent->client.e.state.rot.support) &&
8427                  (!bd->parent->client.e.state.rot.app_set))
8428                {
8429                   /* if transient_for window doesn't support rotation feature,
8430                    * then this window should't be rotated.
8431                    * TODO: need to check whether window supports '0' degree or not.
8432                    */
8433                   will_ang = 0;
8434                   ELBF(ELBT_ROT, 0, bd->client.win,
8435                        "GET ROT ang:%d Transient_For:0x%08x Not support rot",
8436                        will_ang, bd->parent->client.win);
8437                }
8438              else
8439                {
8440                   will_ang = _e_border_rotation_get(bd->parent, will_ang);
8441                   ELBF(ELBT_ROT, 0, bd->client.win,
8442                        "GET ROT ang:%d Transient_For:0x%08x",
8443                        will_ang, bd->parent->client.win);
8444                }
8445           }
8446         else
8447           {
8448              will_ang = _e_border_rotation_get(bd, will_ang);
8449              ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d",
8450                   will_ang, bd->parent ? bd->parent->client.win : 0,
8451                   bd->client.netwm.type);
8452           }
8453      }
8454
8455    if (bd->new_client)
8456      {
8457         _ang = _prev_angle_get(bd->client.win);
8458         if (_ang != -1)
8459           bd->client.e.state.rot.curr = _ang;
8460         ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang);
8461      }
8462
8463    if (bd->client.e.state.rot.curr != will_ang)
8464      ret = will_ang;
8465
8466    return ret;
8467 }
8468
8469
8470 static Eina_Bool
8471 _e_border_rotation_zone_set(E_Zone *zone)
8472 {
8473    E_Border_List *l = NULL;
8474    E_Border *bd = NULL;
8475    Eina_Bool ret = EINA_FALSE;
8476
8477    if (!e_config->wm_win_rotation) return EINA_FALSE;
8478
8479    l = e_container_border_list_last(zone->container);
8480    if (!l) return ret;
8481
8482    /* step 1. make the list needs to be rotated. */
8483    while ((bd = e_container_border_list_prev(l)))
8484      {
8485         if (!bd) continue;
8486
8487         // if this window has parent and window type isn't "ECORE_X_WINDOW_TYPE_NORMAL",
8488         // it will be rotated when parent do rotate itself.
8489         // so skip here.
8490         if ((bd->parent) &&
8491             (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL)) continue;
8492
8493         // default type is "E_BORDER_ROTATION_TYPE_NORMAL",
8494         // but it can be changed to "E_BORDER_ROTATION_TYPE_DEPENDENT" by illume according to its policy.
8495         // if it's not normal type window, will be rotated by illume.
8496         // so skip here.
8497         if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue;
8498
8499         if ((!bd->visible) ||
8500             (!E_INTERSECTS(bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h,
8501                            bd->x, bd->y, bd->w, bd->h))) continue;
8502
8503         if (_e_border_rotatable_check(bd, zone->rot.curr))
8504           {
8505              ELBF(ELBT_ROT, 0, bd->client.win, "ROT_SET(main) curr:%d != TOBE:%d",
8506                   bd->client.e.state.rot.curr, zone->rot.curr);
8507
8508              ret = e_border_rotation_set(bd, zone->rot.curr);
8509           }
8510      }
8511    if (l) e_container_border_list_free(l);
8512
8513    return ret;
8514 }
8515
8516 static Eina_Bool
8517 _e_border_rotation_set_internal(E_Border *bd, int rotation, Eina_Bool *pending)
8518 {
8519    E_Zone *zone = bd->zone;
8520    E_Border_Rotation_Info *info = NULL;
8521    Eina_List *list, *l;
8522    E_Border *child;
8523
8524    if (rotation < 0) return EINA_FALSE;
8525    if (pending) *pending = EINA_FALSE;
8526
8527    /* step 1. check if rotation */
8528    if (!_e_border_rotatable_check(bd, rotation)) return EINA_FALSE;
8529
8530    /* step 2. add to async/sync list */
8531    if ((!zone->rot.block_count) &&
8532        ((!bd->visible) ||
8533         (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))))
8534      {
8535         // send rotation change request later.
8536         // and no need to wait message of rotation done.
8537
8538         // async list add
8539         info = E_NEW(E_Border_Rotation_Info, 1);
8540         if (!info) return EINA_FALSE;
8541         ELB(ELBT_ROT, "ADD ASYNC LIST", 0);
8542         info->bd = bd;
8543         info->ang = rotation;
8544         rot.async_list = eina_list_append(rot.async_list, info);
8545
8546         // add job for sending event.
8547         if (!rot.async_job)
8548           {
8549              ELB(ELBT_ROT, "ADD ASYNC_JOB", bd->client.win);
8550              rot.async_job = ecore_job_add(_e_border_cb_rotation_async_job, zone);
8551           }
8552      }
8553    else
8554      {
8555         // sync list add
8556         info = E_NEW(E_Border_Rotation_Info, 1);
8557         if (!info) return EINA_FALSE;
8558         ELB(ELBT_ROT, "ADD SYNC LIST", 0);
8559         info->bd = bd;
8560         info->ang = rotation;
8561         rot.list = eina_list_append(rot.list, info);
8562
8563         // add job for sending event.
8564         if (!rot.sync_job)
8565           {
8566              ELB(ELBT_ROT, "ADD SYNC_JOB", bd->client.win);
8567              rot.sync_job = ecore_job_add(_e_border_cb_rotation_sync_job, zone);
8568           }
8569
8570         // if there is windows over 2 that has to be rotated or is existed window needs resizing,
8571         // lock the screen.
8572         // but, DO NOT lock the screen when rotation block state.
8573         if ((!zone->rot.block_count) &&
8574             ((eina_list_count(rot.list) == 2)))
8575           e_manager_comp_screen_lock(e_manager_current_get());
8576      }
8577
8578    if (pending) *pending = EINA_TRUE;
8579
8580    /* step 3. search rotatable window in this window's child */
8581    list = _e_border_sub_borders_new(bd);
8582    EINA_LIST_FOREACH(list, l, child)
8583      {
8584         // the window which type is "ECORE_X_WINDOW_TYPE_NORMAL" will be rotated itself.
8585         // it shouldn't be rotated by rotation state of parent window.
8586         if (child->client.netwm.type == ECORE_X_WINDOW_TYPE_NORMAL) continue;
8587         if (_e_border_rotatable_check(child, rotation))
8588           {
8589              ELBF(ELBT_ROT, 0, child->client.win, "ROT_SET(child) curr:%d != TOBE:%d",
8590                   bd->client.e.state.rot.curr, rotation);
8591              e_border_rotation_set(child, rotation);
8592           }
8593      }
8594
8595    /* step 4. if there is vkbd window, send message to prepare rotation */
8596    if (_e_border_is_vkbd(bd))
8597      {
8598         ELB(ELBT_ROT, "PENDING ROT_REQ UNTIL GET PREP_DONE", rot.vkbd_ctrl_win);
8599         if (rot.prepare_timer)
8600           ecore_timer_del(rot.prepare_timer);
8601         rot.prepare_timer = NULL;
8602
8603         if (rot.done_timer)
8604           ecore_timer_del(rot.done_timer);
8605         rot.done_timer = NULL;
8606
8607         ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win);
8608         ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8609                                                       zone->rot.curr,
8610                                                       EINA_FALSE, 1, 1);
8611         rot.prepare_timer = ecore_timer_add(4.0f,
8612                                             _e_border_rotation_change_prepare_timeout,
8613                                             NULL);
8614
8615         rot.wait_prepare_done = EINA_TRUE;
8616      }
8617
8618    bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8619    bd->client.e.state.rot.curr = rotation;
8620
8621    return EINA_TRUE;
8622 }
8623
8624 // check if border is rotatable in ang.
8625 static Eina_Bool
8626 _e_border_rotatable_check(E_Border *bd, int ang)
8627 {
8628    Eina_Bool ret = EINA_FALSE;
8629
8630    if (!bd) return ret;
8631    if (ang < 0) return ret;
8632    if ((!bd->client.e.state.rot.support) && (!bd->client.e.state.rot.app_set)) return ret;
8633    if (e_object_is_del(E_OBJECT(bd))) return ret;
8634
8635    // same with current angle of window, then false return.
8636    if (ang == bd->client.e.state.rot.curr) return ret;
8637
8638    /* basically WM allows only fullscreen window to rotate */
8639    if (bd->client.e.state.rot.preferred_rot == -1)
8640      {
8641         unsigned int i;
8642
8643         if (bd->client.e.state.rot.app_set)
8644           {
8645              if (bd->client.e.state.rot.available_rots &&
8646                  bd->client.e.state.rot.count)
8647                {
8648                   Eina_Bool found = EINA_FALSE;
8649                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8650                     {
8651                        if (bd->client.e.state.rot.available_rots[i] == ang)
8652                          {
8653                             found = EINA_TRUE;
8654                          }
8655                     }
8656                   if (found) ret = EINA_TRUE;
8657                }
8658           }
8659         else
8660           {
8661              ELB(ELBT_ROT, "DO ROT", 0);
8662              ret = EINA_TRUE;
8663           }
8664      }
8665    // if it has preferred rotation angle,
8666    // it will be rotated at border's evaluation time.
8667    // so skip it.
8668    else if (bd->client.e.state.rot.preferred_rot == ang) ret = EINA_TRUE;
8669
8670    return ret;
8671 }
8672
8673 /* check whether virtual keyboard is visible on the zone */
8674 static Eina_Bool
8675 _e_border_is_vkbd(E_Border *bd)
8676 {
8677    if (!e_config->wm_win_rotation) return EINA_FALSE;
8678
8679    if ((rot.vkbd_ctrl_win) &&
8680        (rot.vkbd == bd) &&
8681        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8682        (rot.vkbd->zone == bd->zone) &&
8683        (E_INTERSECTS(bd->zone->x, bd->zone->y,
8684                      bd->zone->w, bd->zone->h,
8685                      rot.vkbd->x, rot.vkbd->y,
8686                      rot.vkbd->w, rot.vkbd->h)))
8687      {
8688         return EINA_TRUE;
8689      }
8690    return EINA_FALSE;
8691 }
8692
8693 static Eina_Bool
8694 _e_border_rotation_change_floating_pos(E_Border *bd, int *x, int *y)
8695 {
8696    int new_x, new_y;
8697    int min_title_width=96;
8698
8699    if (!bd) return EINA_FALSE;
8700    if (!x || !y) return EINA_FALSE;
8701
8702    new_x = bd->x;
8703    new_y = bd->y;
8704
8705    // Portrait -> Landscape,  x= pre_x*2, y=pre_y/2
8706    // Landscape -> Portrait,  x= pre_x/2, y=pre_y*2
8707    // guaranteeing the minimum size of titlebar shown, min_title_width
8708    // so user can initiate drag&drop action after rotation changed.
8709    if (bd->client.e.state.rot.curr == 0)
8710      {
8711         if (bd->client.e.state.rot.prev == 90)
8712           {
8713              new_x = (bd->zone->h - bd->h - bd->y) / 2;
8714              new_y = 2 * bd->x;
8715           }
8716         else if (bd->client.e.state.rot.prev == 270)
8717           {
8718              new_x = bd->y / 2;
8719              new_y = (bd->zone->w - bd->w - bd->x) * 2;
8720           }
8721         else if (bd->client.e.state.rot.prev == 180)
8722           {
8723              new_x = bd->zone->w - bd->x - bd->w;
8724              new_y = bd->zone->h - bd->y - bd->h;
8725           }
8726
8727         if(new_x + bd->w < min_title_width)
8728           {
8729              new_x = min_title_width - bd->w;
8730           }
8731         else if(new_x > bd->zone->w - min_title_width)
8732           {
8733              new_x = bd->zone->w - min_title_width;
8734           }
8735      }
8736    else if (bd->client.e.state.rot.curr == 90)
8737      {
8738         if (bd->client.e.state.rot.prev == 0)
8739           {
8740              new_x = bd->y / 2;
8741              new_y = bd->zone->h - (2 * bd->x) - bd->w;
8742           }
8743         else if (bd->client.e.state.rot.prev == 270)
8744           {
8745              new_x = bd->zone->w - bd->x - bd->w;
8746              new_y = bd->zone->h - bd->y - bd->h;
8747           }
8748         else if (bd->client.e.state.rot.prev == 180)
8749           {
8750              new_x = (bd->zone->h - bd->y - bd->h) / 2;
8751              new_y = bd->zone->h - (2 * (bd->zone->w - bd->x - bd->w)) - bd->w;
8752           }
8753
8754         if(new_y > bd->zone->h - min_title_width)
8755           {
8756              new_y = bd->zone->h - min_title_width;
8757           }
8758         else if(new_y < min_title_width - bd->w)
8759           {
8760              new_y = min_title_width - bd->w;
8761           }
8762      }
8763    else if (bd->client.e.state.rot.curr == 270)
8764      {
8765         if (bd->client.e.state.rot.prev == 0)
8766           {
8767              new_x = bd->zone->w - bd->h - (bd->y / 2);
8768              new_y = bd->x * 2;
8769           }
8770         else if (bd->client.e.state.rot.prev == 90)
8771           {
8772              new_x = bd->zone->w - bd->x - bd->w;
8773              new_y = bd->zone->h - bd->y - bd->h;
8774           }
8775         else if (bd->client.e.state.rot.prev == 180)
8776           {
8777              new_x = bd->zone->w - bd->x - bd->w;
8778              new_y = bd->zone->h - bd->y - bd->h;
8779
8780              new_x = bd->zone->w - bd->h - ((bd->zone->h - bd->y - bd->h) / 2);
8781              new_y = (bd->zone->w - bd->x - bd->w) * 2;
8782           }
8783
8784         if(new_y >  bd->zone->h - min_title_width)
8785           {
8786              new_y = bd->zone->h - min_title_width;
8787           }
8788         else if( new_y + bd->w < min_title_width)
8789           {
8790              new_y = min_title_width - bd->w ;
8791           }
8792      }
8793    else if (bd->client.e.state.rot.curr == 180)
8794      {
8795         if (bd->client.e.state.rot.prev == 0)
8796           {
8797              new_x = bd->zone->w - bd->x - bd->w;
8798              new_y = bd->zone->h - bd->y - bd->h;
8799           }
8800         else if (bd->client.e.state.rot.prev == 90)
8801           {
8802              new_x = bd->zone->w - ((bd->zone->h - bd->h - bd->y) / 2) - bd->h;
8803              new_y = bd->zone->h - (2 * bd->x) - bd->w;
8804           }
8805         else if (bd->client.e.state.rot.prev == 270)
8806           {
8807              new_x = bd->zone->w - (bd->y / 2) - bd->h;
8808              new_y = bd->zone->h - ((bd->zone->w - bd->w - bd->x) * 2) - bd->w;
8809           }
8810
8811         if(new_x + bd->w < min_title_width)
8812           {
8813              new_x = min_title_width - bd->w;
8814           }
8815         else if(new_x > bd->zone->w - min_title_width)
8816           {
8817              new_x = bd->zone->w - min_title_width;
8818           }
8819      }
8820
8821    ELBF(ELBT_ROT, 0, bd->client.win,
8822         "Floating Mode. ANGLE (%d->%d), POS (%d,%d) -> (%d,%d)",
8823         bd->client.e.state.rot.prev, bd->client.e.state.rot.curr,
8824         bd->x, bd->y, new_x, new_y);
8825
8826    if ((new_x == *x) &&
8827        (new_y == *y))
8828      {
8829         return EINA_FALSE;
8830      }
8831
8832    *x = new_x;
8833    *y = new_y;
8834
8835    return EINA_TRUE;
8836 }
8837
8838 #define SIZE_EQUAL_TO_ZONE(a, z) \
8839    ((((a)->w) == ((z)->w)) &&    \
8840     (((a)->h) == ((z)->h)))
8841 static Eina_Bool
8842 _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h)
8843 {
8844    E_Zone *zone = bd->zone;
8845    int rot_dif;
8846    int _x, _y, _w, _h;
8847    Eina_Bool move = EINA_FALSE;
8848    Eina_Bool hint = EINA_FALSE;
8849    Eina_Bool resize = EINA_FALSE;
8850
8851    if (x) *x = bd->x;
8852    if (y) *y = bd->y;
8853    if (w) *w = bd->w;
8854    if (h) *h = bd->h;
8855
8856    if (SIZE_EQUAL_TO_ZONE(bd, zone)) return resize;
8857
8858    ELB(ELBT_ROT, "SIZE DIFF WITH ZONE", 0);
8859    ELBF(ELBT_ROT, 0, bd->client.win, "ORIGIN_SIZE name:%s (%d,%d) %dx%d",
8860         bd->client.icccm.name, bd->x, bd->y, bd->w, bd->h);
8861
8862    hint = _e_border_rotation_geom_get(bd, bd->zone, rotation,
8863                                       &_x, &_y, &_w, &_h, &move);
8864    if (hint)
8865      {
8866         _e_border_move_resize_internal(bd, _x, _y, _w, _h, EINA_TRUE, move);
8867         resize = EINA_TRUE;
8868         ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
8869              bd->client.icccm.name, _x, _y, _w, _h);
8870      }
8871    else
8872      {
8873         _x = bd->x; _y = bd->y;
8874         _w = bd->w; _h = bd->h;
8875
8876         if (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)
8877           move = _e_border_rotation_change_floating_pos(bd, &_x, &_y);
8878         else
8879           move = EINA_FALSE;
8880
8881         rot_dif = bd->client.e.state.rot.prev - rotation;
8882         if (rot_dif < 0) rot_dif = -rot_dif;
8883         if (rot_dif != 180)
8884           {
8885              if (w != h)
8886                {
8887                   _w = bd->h;
8888                   _h = bd->w;
8889                   resize = EINA_TRUE;
8890
8891                   _e_border_move_resize_internal(bd, _x, _y, _w, _h,
8892                                                  EINA_TRUE, EINA_TRUE);
8893                   ELBF(ELBT_ROT, 0, bd->client.win, "MANUAL_RESIZE name:%s (%d,%d) %dx%d",
8894                        bd->client.icccm.name, _x, _y, _w, _h);
8895
8896                }
8897           }
8898
8899         if (!resize && move)
8900           _e_border_move_internal(bd, _x, _y, EINA_TRUE);
8901      }
8902
8903    if (resize)
8904      {
8905         if (x) *x = _x;
8906         if (y) *y = _y;
8907         if (w) *w = _w;
8908         if (h) *h = _h;
8909      }
8910
8911    return resize;
8912 }
8913
8914 static Eina_Bool
8915 _e_border_cb_window_configure(void *data    __UNUSED__,
8916                               int   ev_type __UNUSED__,
8917                               void         *ev)
8918 {
8919    Ecore_X_Event_Window_Configure *e = ev;
8920    E_Border_Rotation_Info *info = NULL;
8921    Eina_List *l;
8922    Eina_Bool found = EINA_FALSE;
8923
8924    if (!e) return ECORE_CALLBACK_PASS_ON;
8925    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8926
8927    E_Border *bd = e_border_find_by_client_window(e->win);
8928    if (!bd) return ECORE_CALLBACK_PASS_ON;
8929
8930    if (bd->client.e.state.rot.pending_change_request)
8931      {
8932         if ((e->w == bd->w) && (e->h == bd->h))
8933           {
8934              ELB(ELBT_BD, "GET CONFIGURE_NOTI (ROTATION)", bd->client.win);
8935              bd->client.e.state.rot.pending_change_request = 0;
8936
8937              if ((bd->client.e.state.rot.wait_for_done) &&
8938                  (bd->client.e.state.rot.wait_done_ang == bd->client.e.state.rot.curr)) goto end;
8939
8940              // if this window is rotation dependent window and zone is blocked to rotate,
8941              // then skip here, request will be sent after cancel block.
8942              if ((bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_DEPENDENT) &&
8943                  (bd->zone->rot.block_count)) goto end;
8944
8945              EINA_LIST_FOREACH(rot.list, l, info)
8946                 if (info->bd == bd) found = EINA_TRUE;
8947              // send request message if it's async rotation window,
8948              // even if wait prepare done.
8949              if ((found) && (rot.wait_prepare_done)) goto end;
8950
8951              ELBF(ELBT_ROT, 0, bd->client.win,
8952                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
8953                   bd->client.e.state.rot.curr,
8954                   bd->w, bd->h);
8955              ecore_x_e_window_rotation_change_request_send(bd->client.win,
8956                                                            bd->client.e.state.rot.curr);
8957              bd->client.e.state.rot.wait_for_done = 1;
8958              bd->client.e.state.rot.wait_done_ang = bd->client.e.state.rot.curr;
8959           }
8960      }
8961
8962 end:
8963    return ECORE_CALLBACK_PASS_ON;
8964 }
8965
8966 static Eina_Bool
8967 _e_border_rotation_geom_get(E_Border  *bd,
8968                             E_Zone    *zone,
8969                             int        ang,
8970                             int       *x,
8971                             int       *y,
8972                             int       *w,
8973                             int       *h,
8974                             Eina_Bool *move)
8975 {
8976    if (!e_config->wm_win_rotation) return EINA_FALSE;
8977
8978    Eina_Bool res = EINA_FALSE;
8979    Eina_Bool _move = EINA_TRUE;
8980    int _x = bd->x;
8981    int _y = bd->y;
8982    int _w = bd->w;
8983    int _h = bd->h;
8984
8985    if (x) *x = bd->x;
8986    if (y) *y = bd->y;
8987    if (w) *w = bd->w;
8988    if (h) *h = bd->h;
8989    if (move) *move = EINA_TRUE;
8990
8991    if (bd->client.e.state.rot.geom_hint)
8992      {
8993         switch (ang)
8994           {
8995            case   0:
8996               _w = bd->client.e.state.rot.geom[0].w;
8997               _h = bd->client.e.state.rot.geom[0].h;
8998               if (_w == 0) _w = bd->w;
8999               if (_h == 0) _h = bd->h;
9000               _x = 0; _y = zone->h - _h;
9001               break;
9002            case  90:
9003               _w = bd->client.e.state.rot.geom[1].w;
9004               _h = bd->client.e.state.rot.geom[1].h;
9005               if (_w == 0) _w = bd->w;
9006               if (_h == 0) _h = bd->h;
9007               _x = zone->w - _w; _y = 0;
9008               break;
9009            case 180:
9010               _w = bd->client.e.state.rot.geom[2].w;
9011               _h = bd->client.e.state.rot.geom[2].h;
9012               if (_w == 0) _w = bd->w;
9013               if (_h == 0) _h = bd->h;
9014               _x = 0; _y = 0;
9015               break;
9016            case 270:
9017               _w = bd->client.e.state.rot.geom[3].w;
9018               _h = bd->client.e.state.rot.geom[3].h;
9019               if (_w == 0) _w = bd->w;
9020               if (_h == 0) _h = bd->h;
9021               _x = 0; _y = 0;
9022               break;
9023           }
9024
9025         if (x) *x = _x;
9026         if (y) *y = _y;
9027         if (w) *w = _w;
9028         if (h) *h = _h;
9029
9030         if (!((rot.vkbd) && (rot.vkbd == bd)))
9031           {
9032              if (x) *x = bd->x;
9033              if (y) *y = bd->y;
9034              if (move) *move = EINA_FALSE;
9035           }
9036
9037         res = EINA_TRUE;
9038      }
9039
9040    if (res)
9041      {
9042         _x = 0; _y = 0; _w = 0; _h = 0;
9043         if (x) _x = *x;
9044         if (y) _y = *y;
9045         if (w) _w = *w;
9046         if (h) _h = *h;
9047         if (move) _move = *move;
9048
9049         ELBF(ELBT_ROT, 1, bd->client.win,
9050              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
9051              ang, _x, _y, _w, _h, _move);
9052      }
9053
9054    return res;
9055 }
9056 #endif
9057
9058 static Eina_Bool
9059 _e_border_post_move_resize_job(void *data)
9060 {
9061    E_Border *bd;
9062
9063    bd = (E_Border *)data;
9064    if (bd->post_move)
9065      {
9066         E_Border *tmp;
9067         Eina_List *l;
9068
9069         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
9070           ecore_x_window_move(tmp->win,
9071                               bd->x +
9072                               bd->client_inset.l +
9073                               bd->fx.x +
9074                               tmp->client.e.state.video_position.x,
9075                               bd->y +
9076                               bd->client_inset.t +
9077                               bd->fx.y +
9078                               tmp->client.e.state.video_position.y);
9079      }
9080    if (bd->client.e.state.video)
9081      {
9082         E_Border *parent;
9083
9084         parent = bd->client.e.state.video_parent_border;
9085         ecore_x_window_move(bd->win,
9086                             parent->x +
9087                             parent->client_inset.l +
9088                             parent->fx.x +
9089                             bd->client.e.state.video_position.x,
9090                             parent->y +
9091                             parent->client_inset.t +
9092                             parent->fx.y +
9093                             bd->client.e.state.video_position.y);
9094      }
9095    else if ((bd->post_move) && (bd->post_resize))
9096      {
9097         ecore_x_window_move_resize(bd->win,
9098                                    bd->x + bd->fx.x,
9099                                    bd->y + bd->fx.y,
9100                                    bd->w, bd->h);
9101      }
9102    else if (bd->post_move)
9103      {
9104         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
9105      }
9106    else if (bd->post_resize)
9107      {
9108         ecore_x_window_resize(bd->win, bd->w, bd->h);
9109      }
9110
9111    if (bd->client.e.state.video)
9112      {
9113         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
9114                 bd->win,
9115                 bd->client.e.state.video_parent_border->x +
9116                 bd->client.e.state.video_parent_border->client_inset.l +
9117                 bd->client.e.state.video_parent_border->fx.x +
9118                 bd->client.e.state.video_position.x,
9119                 bd->client.e.state.video_parent_border->y +
9120                 bd->client.e.state.video_parent_border->client_inset.t +
9121                 bd->client.e.state.video_parent_border->fx.y +
9122                 bd->client.e.state.video_position.y,
9123                 bd->w, bd->h);
9124      }
9125
9126    if (bd->post_show)
9127      {
9128         if (bd->visible)
9129           {
9130              bd->post_job = NULL;
9131              _e_border_show(bd);
9132           }
9133      }
9134    bd->post_show = 0;
9135    bd->post_move = 0;
9136    bd->post_resize = 0;
9137    bd->post_job = NULL;
9138    return ECORE_CALLBACK_CANCEL;
9139 }
9140
9141 static void
9142 _e_border_container_layout_hook(E_Container *con)
9143 {
9144    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
9145 }
9146
9147 static void
9148 _e_border_eval0(E_Border *bd)
9149 {
9150    int change_urgent = 0;
9151    int rem_change = 0;
9152 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9153    Eina_Bool need_desk_set = EINA_FALSE;
9154 #endif
9155 #ifdef _F_ZONE_WINDOW_ROTATION_
9156    Eina_Bool need_rotation_set = EINA_FALSE;
9157
9158    if ((e_config->wm_win_rotation) &&
9159        (bd->client.icccm.fetch.transient_for))
9160      {
9161         if (((rot.vkbd) && (rot.vkbd == bd)) ||
9162             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
9163           {
9164              need_rotation_set = EINA_TRUE;
9165              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
9166           }
9167      }
9168 #endif
9169
9170    if (e_object_is_del(E_OBJECT(bd)))
9171      {
9172         CRI("_e_border_eval(%p) with deleted border!\n", bd);
9173         bd->changed = 0;
9174         return;
9175      }
9176
9177    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
9178
9179    bd->changes.border = 0;
9180
9181    /* fetch any info queued to be fetched */
9182    if (bd->client.netwm.fetch.state)
9183      {
9184         e_hints_window_state_get(bd);
9185         bd->client.netwm.fetch.state = 0;
9186         rem_change = 1;
9187      }
9188    if (bd->client.icccm.fetch.client_leader)
9189      {
9190         /* TODO: What do to if the client leader isn't mapped yet? */
9191         E_Border *bd_leader = NULL;
9192
9193         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
9194         if (bd->client.icccm.client_leader)
9195           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
9196         if (bd->leader)
9197           {
9198              if (bd->leader != bd_leader)
9199                {
9200                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
9201                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
9202                   bd->leader = NULL;
9203                }
9204              else
9205                bd_leader = NULL;
9206           }
9207         /* If this border is the leader of the group, don't register itself */
9208         if ((bd_leader) && (bd_leader != bd))
9209           {
9210              bd_leader->group = eina_list_append(bd_leader->group, bd);
9211              bd->leader = bd_leader;
9212              /* Only set the window modal to the leader it there is no parent */
9213              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
9214                  ((!bd->parent) || (bd->parent->modal != bd)))
9215                {
9216                   bd->leader->modal = bd;
9217                   if (bd->leader->focused)
9218                     e_border_focus_set(bd, 1, 1);
9219                   else
9220                     {
9221                        Eina_List *l;
9222                        E_Border *child;
9223
9224                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9225                          {
9226                             if ((child != bd) && (child->focused))
9227                               e_border_focus_set(bd, 1, 1);
9228                          }
9229                     }
9230                }
9231           }
9232         bd->client.icccm.fetch.client_leader = 0;
9233         rem_change = 1;
9234      }
9235    if (bd->client.icccm.fetch.title)
9236      {
9237         char *title = ecore_x_icccm_title_get(bd->client.win);
9238         eina_stringshare_replace(&bd->client.icccm.title, title);
9239         if (title) free(title);
9240
9241         if (bd->bg_object)
9242           edje_object_part_text_set(bd->bg_object, "e.text.title",
9243                                     bd->client.icccm.title);
9244         bd->client.icccm.fetch.title = 0;
9245         rem_change = 1;
9246      }
9247    if (bd->client.netwm.fetch.name)
9248      {
9249         char *name;
9250         ecore_x_netwm_name_get(bd->client.win, &name);
9251         eina_stringshare_replace(&bd->client.netwm.name, name);
9252         if (name) free(name);
9253
9254         if (bd->bg_object)
9255           edje_object_part_text_set(bd->bg_object, "e.text.title",
9256                                     bd->client.netwm.name);
9257         bd->client.netwm.fetch.name = 0;
9258         rem_change = 1;
9259      }
9260    if (bd->client.icccm.fetch.name_class)
9261      {
9262         const char *pname, *pclass;
9263         char *nname, *nclass;
9264
9265         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
9266         pname = bd->client.icccm.name;
9267         pclass = bd->client.icccm.class;
9268         bd->client.icccm.name = eina_stringshare_add(nname);
9269         bd->client.icccm.class = eina_stringshare_add(nclass);
9270         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
9271           e_bindings_mapping_change_enable(EINA_FALSE);
9272 #ifdef _F_ZONE_WINDOW_ROTATION_
9273         if (e_config->wm_win_rotation)
9274           {
9275              if ((bd->client.icccm.name) && (bd->client.icccm.class))
9276                {
9277                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
9278                       (!strcmp(bd->client.icccm.class, "ISF")))
9279                     {
9280                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
9281                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
9282                        rot.vkbd = bd;
9283                     }
9284                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
9285                            (!strcmp(bd->client.icccm.class, "ISF")))
9286                     {
9287                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
9288                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
9289                        rot.vkbd_prediction = bd;
9290                     }
9291                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
9292                            (!strcmp(bd->client.icccm.class, "ISF")))
9293                     {
9294                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
9295                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
9296                     }
9297                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
9298                            (!strcmp(bd->client.icccm.class, "ISF")))
9299                     {
9300                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
9301                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
9302                     }
9303                }
9304           }
9305 #endif
9306         if (nname) free(nname);
9307         if (nclass) free(nclass);
9308
9309         if (!((bd->client.icccm.name == pname) &&
9310               (bd->client.icccm.class == pclass)))
9311           bd->changes.icon = 1;
9312
9313         if (pname) eina_stringshare_del(pname);
9314         if (pclass) eina_stringshare_del(pclass);
9315         bd->client.icccm.fetch.name_class = 0;
9316         bd->changes.icon = 1;
9317         rem_change = 1;
9318      }
9319    if (bd->client.icccm.fetch.state)
9320      {
9321         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
9322         bd->client.icccm.fetch.state = 0;
9323         rem_change = 1;
9324      }
9325    if (bd->client.e.fetch.state)
9326      {
9327         e_hints_window_e_state_get(bd);
9328         bd->client.e.fetch.state = 0;
9329         rem_change = 1;
9330      }
9331 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9332    if (bd->client.e.fetch.profile_list)
9333      {
9334         const char **profiles = NULL;
9335         const char *str;
9336         int num = 0, i;
9337
9338         if (bd->client.e.state.profile)
9339           eina_stringshare_del(bd->client.e.state.profile);
9340         EINA_LIST_FREE(bd->client.e.state.profiles, str)
9341           {
9342              if (str) eina_stringshare_del(str);
9343           }
9344         bd->client.e.state.profile = NULL;
9345         bd->client.e.state.profiles = NULL;
9346         bd->client.e.state.profile_list = 0;
9347
9348         if (ecore_x_e_window_profile_list_get(bd->client.win,
9349                                               &profiles, &num))
9350           {
9351              bd->client.e.state.profile_list = 1;
9352              for (i = 0; i < num; i++)
9353                {
9354                   str = eina_stringshare_add(profiles[i]);
9355                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
9356                }
9357
9358              /* We should set desk to contain given border after creating E_BORDER_ADD event.
9359               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
9360               */
9361              need_desk_set = EINA_TRUE;
9362           }
9363         else
9364           {
9365              if (strcmp(bd->desk->window_profile,
9366                         e_config->desktop_default_window_profile) != 0)
9367                {
9368                   ecore_x_e_window_profile_set(bd->client.win,
9369                                                bd->desk->window_profile);
9370                }
9371           }
9372
9373         if (profiles)
9374           {
9375              for (i = 0; i < num; i++)
9376                 if (profiles[i]) free(profiles[i]);
9377              free(profiles);
9378           }
9379
9380         bd->client.e.fetch.profile_list = 0;
9381      }
9382 #endif
9383 #ifdef _F_ZONE_WINDOW_ROTATION_
9384    if ((e_config->wm_win_rotation) &&
9385        (bd->client.e.fetch.rot.support))
9386      {
9387         int ret = 0;
9388         unsigned int support = 0;
9389
9390         ret = ecore_x_window_prop_card32_get
9391           (bd->client.win,
9392           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
9393           &support, 1);
9394
9395         bd->client.e.state.rot.support = 0;
9396         if ((ret == 1) && (support == 1))
9397           bd->client.e.state.rot.support = 1;
9398
9399         if (bd->client.e.state.rot.support)
9400           need_rotation_set = EINA_TRUE;
9401
9402         bd->client.e.fetch.rot.support = 0;
9403      }
9404    if ((e_config->wm_win_rotation) &&
9405        (bd->client.e.fetch.rot.geom_hint))
9406      {
9407         Eina_Rectangle r[4];
9408         int i, x, y, w, h;
9409         bd->client.e.state.rot.geom_hint = 0;
9410         for (i = 0; i < 4; i++)
9411           {
9412              r[i].x = bd->client.e.state.rot.geom[i].x;
9413              r[i].y = bd->client.e.state.rot.geom[i].y;
9414              r[i].w = bd->client.e.state.rot.geom[i].w;
9415              r[i].h = bd->client.e.state.rot.geom[i].h;
9416
9417              bd->client.e.state.rot.geom[i].x = 0;
9418              bd->client.e.state.rot.geom[i].y = 0;
9419              bd->client.e.state.rot.geom[i].w = 0;
9420              bd->client.e.state.rot.geom[i].h = 0;
9421           }
9422
9423         for (i = 0; i < 4; i++)
9424           {
9425              x = 0; y = 0; w = 0; h = 0;
9426              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
9427                {
9428                   bd->client.e.state.rot.geom_hint = 1;
9429                   bd->client.e.state.rot.geom[i].x = x;
9430                   bd->client.e.state.rot.geom[i].y = y;
9431                   bd->client.e.state.rot.geom[i].w = w;
9432                   bd->client.e.state.rot.geom[i].h = h;
9433
9434                   if (!((r[i].x == x) && (r[i].y == y) &&
9435                         (r[i].w == w) && (r[i].h == h)))
9436                     {
9437                        need_rotation_set = EINA_TRUE;
9438                     }
9439                }
9440           }
9441         bd->client.e.fetch.rot.geom_hint = 0;
9442      }
9443    if ((e_config->wm_win_rotation) &&
9444        (bd->client.e.fetch.rot.app_set))
9445      {
9446         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
9447         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
9448         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
9449
9450         if (_prev_app_set != bd->client.e.state.rot.app_set)
9451           need_rotation_set = EINA_TRUE;
9452
9453         bd->client.e.fetch.rot.app_set = 0;
9454      }
9455    if ((e_config->wm_win_rotation) &&
9456        (bd->client.e.fetch.rot.preferred_rot))
9457      {
9458         int r = 0, _prev_preferred_rot;
9459         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
9460         bd->client.e.state.rot.preferred_rot = -1;
9461         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
9462           {
9463              bd->client.e.state.rot.preferred_rot = r;
9464              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
9465           }
9466         else
9467           {
9468              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
9469           }
9470
9471         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
9472           need_rotation_set = EINA_TRUE;
9473
9474         bd->client.e.fetch.rot.preferred_rot = 0;
9475      }
9476    if ((e_config->wm_win_rotation) &&
9477        (bd->client.e.fetch.rot.available_rots))
9478      {
9479         Eina_Bool res, diff = EINA_FALSE;
9480         int *rots = NULL;
9481         unsigned int count = 0, i = 0;
9482         int _prev_rots[4] = { -1, };
9483
9484         if (bd->client.e.state.rot.available_rots)
9485           {
9486              memcpy(_prev_rots,
9487                     bd->client.e.state.rot.available_rots,
9488                     (sizeof(int) * bd->client.e.state.rot.count));
9489
9490              E_FREE(bd->client.e.state.rot.available_rots);
9491           }
9492
9493         bd->client.e.state.rot.count = 0;
9494
9495         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
9496                                                                 &rots, &count);
9497         if ((res) && (count > 0) && (rots))
9498           {
9499              bd->client.e.state.rot.available_rots = rots;
9500              bd->client.e.state.rot.count = count;
9501
9502              for (i = 0; i < count; i++)
9503                {
9504                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
9505                   if ((!diff) && (_prev_rots[i] != rots[i]))
9506                     {
9507                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
9508                             count, i, _prev_rots[i], rots[i]);
9509                        diff = EINA_TRUE;
9510                     }
9511                }
9512           }
9513         else
9514           {
9515              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9516              diff = EINA_TRUE;
9517           }
9518
9519         if (diff) need_rotation_set = EINA_TRUE;
9520         bd->client.e.fetch.rot.available_rots = 0;
9521      }
9522 #endif
9523    if (bd->client.netwm.fetch.type)
9524      {
9525         e_hints_window_type_get(bd);
9526         if ((!bd->lock_border) || (!bd->client.border.name))
9527           bd->client.border.changed = 1;
9528
9529         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9530           {
9531              if (!bd->client.netwm.state.skip_pager)
9532                {
9533                   bd->client.netwm.state.skip_pager = 1;
9534                   bd->client.netwm.update.state = 1;
9535                }
9536              if (!bd->client.netwm.state.skip_taskbar)
9537                {
9538                   bd->client.netwm.state.skip_taskbar = 1;
9539                   bd->client.netwm.update.state = 1;
9540                }
9541           }
9542         bd->client.netwm.fetch.type = 0;
9543      }
9544    if (bd->client.icccm.fetch.machine)
9545      {
9546         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9547
9548         if ((!machine) && (bd->client.icccm.client_leader))
9549           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9550
9551         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9552         if (machine) free(machine);
9553
9554         bd->client.icccm.fetch.machine = 0;
9555         rem_change = 1;
9556      }
9557    if (bd->client.icccm.fetch.command)
9558      {
9559         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9560           {
9561              int i;
9562
9563              for (i = 0; i < bd->client.icccm.command.argc; i++)
9564                free(bd->client.icccm.command.argv[i]);
9565              free(bd->client.icccm.command.argv);
9566           }
9567         bd->client.icccm.command.argc = 0;
9568         bd->client.icccm.command.argv = NULL;
9569         ecore_x_icccm_command_get(bd->client.win,
9570                                   &(bd->client.icccm.command.argc),
9571                                   &(bd->client.icccm.command.argv));
9572         if ((bd->client.icccm.client_leader) &&
9573             (!bd->client.icccm.command.argv))
9574           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9575                                     &(bd->client.icccm.command.argc),
9576                                     &(bd->client.icccm.command.argv));
9577         bd->client.icccm.fetch.command = 0;
9578         rem_change = 1;
9579      }
9580    if (bd->client.icccm.fetch.hints)
9581      {
9582         Eina_Bool accepts_focus, is_urgent;
9583
9584         accepts_focus = EINA_TRUE;
9585         is_urgent = EINA_FALSE;
9586         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9587         if (ecore_x_icccm_hints_get(bd->client.win,
9588                                     &accepts_focus,
9589                                     &bd->client.icccm.initial_state,
9590                                     &bd->client.icccm.icon_pixmap,
9591                                     &bd->client.icccm.icon_mask,
9592                                     &bd->client.icccm.icon_window,
9593                                     &bd->client.icccm.window_group,
9594                                     &is_urgent))
9595           {
9596              bd->client.icccm.accepts_focus = accepts_focus;
9597              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9598                change_urgent = 1;
9599              bd->client.icccm.urgent = is_urgent;
9600
9601              /* If this is a new window, set the state as requested. */
9602              if ((bd->new_client) &&
9603                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9604                {
9605                   e_border_iconify(bd);
9606                   e_border_hide(bd, 1);
9607                }
9608           }
9609         bd->client.icccm.fetch.hints = 0;
9610         rem_change = 1;
9611      }
9612    if (bd->client.icccm.fetch.size_pos_hints)
9613      {
9614         Eina_Bool request_pos;
9615
9616         request_pos = EINA_FALSE;
9617         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9618                                              &request_pos,
9619                                              &bd->client.icccm.gravity,
9620                                              &bd->client.icccm.min_w,
9621                                              &bd->client.icccm.min_h,
9622                                              &bd->client.icccm.max_w,
9623                                              &bd->client.icccm.max_h,
9624                                              &bd->client.icccm.base_w,
9625                                              &bd->client.icccm.base_h,
9626                                              &bd->client.icccm.step_w,
9627                                              &bd->client.icccm.step_h,
9628                                              &bd->client.icccm.min_aspect,
9629                                              &bd->client.icccm.max_aspect))
9630           {
9631              bd->client.icccm.request_pos = request_pos;
9632           }
9633         else
9634           {
9635           }
9636         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9637         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9638         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9639         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9640         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9641         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9642         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9643         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9644         // if doing a resize, fix it up
9645         if (bd->resize_mode != RESIZE_NONE)
9646           {
9647              int x, y, w, h, new_w, new_h;
9648
9649              x = bd->x;
9650              y = bd->y;
9651              w = bd->w;
9652              h = bd->h;
9653              new_w = w;
9654              new_h = h;
9655              e_border_resize_limit(bd, &new_w, &new_h);
9656              if ((bd->resize_mode == RESIZE_TL) ||
9657                  (bd->resize_mode == RESIZE_L) ||
9658                  (bd->resize_mode == RESIZE_BL))
9659                x += (w - new_w);
9660              if ((bd->resize_mode == RESIZE_TL) ||
9661                  (bd->resize_mode == RESIZE_T) ||
9662                  (bd->resize_mode == RESIZE_TR))
9663                y += (h - new_h);
9664              e_border_move_resize(bd, x, y, new_w, new_h);
9665           }
9666         bd->client.icccm.fetch.size_pos_hints = 0;
9667         rem_change = 1;
9668      }
9669    if (bd->client.icccm.fetch.protocol)
9670      {
9671         int i, num;
9672         Ecore_X_WM_Protocol *proto;
9673
9674         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9675         if (proto)
9676           {
9677              for (i = 0; i < num; i++)
9678                {
9679                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9680                     bd->client.icccm.delete_request = 1;
9681                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9682                     bd->client.icccm.take_focus = 1;
9683                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9684                     bd->client.netwm.ping = 1;
9685                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9686                     {
9687                        bd->client.netwm.sync.request = 1;
9688                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9689                                                            &bd->client.netwm.sync.counter))
9690                          bd->client.netwm.sync.request = 0;
9691                     }
9692                }
9693              free(proto);
9694           }
9695         if (bd->client.netwm.ping)
9696           e_border_ping(bd);
9697         else
9698           {
9699              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9700              bd->ping_poller = NULL;
9701           }
9702         bd->client.icccm.fetch.protocol = 0;
9703      }
9704    if (bd->client.icccm.fetch.transient_for)
9705      {
9706         /* TODO: What do to if the transient for isn't mapped yet? */
9707         E_Border *bd_parent = NULL;
9708 #ifdef _F_DEICONIFY_APPROVE_
9709         Eina_Bool change_parent = EINA_FALSE;
9710 #endif
9711
9712         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9713         if (bd->client.icccm.transient_for)
9714           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9715         /* If we already have a parent, remove it */
9716         if (bd->parent)
9717           {
9718              if (bd_parent != bd->parent)
9719                {
9720                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9721                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9722                   bd->parent = NULL;
9723                }
9724              else
9725                bd_parent = NULL;
9726           }
9727         if ((bd_parent) && (bd_parent != bd) &&
9728             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9729           {
9730              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9731              bd->parent = bd_parent;
9732 #ifdef _F_DEICONIFY_APPROVE_
9733              change_parent = EINA_TRUE;
9734 #endif
9735           }
9736         if (bd->parent)
9737           {
9738              e_border_layer_set(bd, bd->parent->layer);
9739              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9740                {
9741                   Ecore_X_Window_Attributes attr;
9742                   bd->parent->modal = bd;
9743                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9744                   bd->parent->saved.event_mask = attr.event_mask.mine;
9745                   bd->parent->lock_close = 1;
9746                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9747                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9748                }
9749
9750              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9751                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9752                bd->take_focus = 1;
9753           }
9754
9755 #ifdef _F_DEICONIFY_APPROVE_
9756         if (change_parent)
9757           {
9758              bd->client.e.state.deiconify_approve.render_done = 0;
9759
9760              E_Border *ancestor_bd;
9761              ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
9762              if ((ancestor_bd) &&
9763                  (!e_object_is_del(E_OBJECT(ancestor_bd))))
9764                {
9765                   ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
9766                   bd->client.e.state.deiconify_approve.ancestor = NULL;
9767
9768                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
9769                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
9770                     {
9771                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
9772                          {
9773                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
9774                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
9775                             e_border_uniconify(ancestor_bd);
9776                          }
9777                     }
9778                }
9779           }
9780 #endif
9781         bd->client.icccm.fetch.transient_for = 0;
9782         rem_change = 1;
9783      }
9784    if (bd->client.icccm.fetch.window_role)
9785      {
9786         char *role = ecore_x_icccm_window_role_get(bd->client.win);
9787         eina_stringshare_replace(&bd->client.icccm.window_role, role);
9788         if (role) free(role);
9789
9790         bd->client.icccm.fetch.window_role = 0;
9791         rem_change = 1;
9792      }
9793    if (bd->client.icccm.fetch.icon_name)
9794      {
9795         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
9796         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
9797         if (icon_name) free(icon_name);
9798
9799         bd->client.icccm.fetch.icon_name = 0;
9800         rem_change = 1;
9801      }
9802    if (bd->client.netwm.fetch.icon_name)
9803      {
9804         char *icon_name;
9805         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
9806         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
9807         if (icon_name) free(icon_name);
9808
9809         bd->client.netwm.fetch.icon_name = 0;
9810         rem_change = 1;
9811      }
9812    if (bd->client.netwm.fetch.icon)
9813      {
9814         int i;
9815         if (bd->client.netwm.icons)
9816           {
9817              for (i = 0; i < bd->client.netwm.num_icons; i++)
9818                {
9819                   free(bd->client.netwm.icons[i].data);
9820                   bd->client.netwm.icons[i].data = NULL;
9821                }
9822              free(bd->client.netwm.icons);
9823           }
9824         bd->client.netwm.icons = NULL;
9825         bd->client.netwm.num_icons = 0;
9826         if (ecore_x_netwm_icons_get(bd->client.win,
9827                                      &bd->client.netwm.icons,
9828                                      &bd->client.netwm.num_icons))
9829           {
9830              // unless the rest of e17 uses border icons OTHER than icon #0
9831              // then free the rest that we don't need anymore.
9832              for (i = 1; i < bd->client.netwm.num_icons; i++)
9833                {
9834                   free(bd->client.netwm.icons[i].data);
9835                   bd->client.netwm.icons[i].data = NULL;
9836                }
9837              bd->client.netwm.num_icons = 1;
9838              bd->changes.icon = 1;
9839           }
9840         bd->client.netwm.fetch.icon = 0;
9841      }
9842    if (bd->client.netwm.fetch.user_time)
9843      {
9844         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
9845         bd->client.netwm.fetch.user_time = 0;
9846      }
9847    if (bd->client.netwm.fetch.strut)
9848      {
9849         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
9850                                              &bd->client.netwm.strut.left,
9851                                              &bd->client.netwm.strut.right,
9852                                              &bd->client.netwm.strut.top,
9853                                              &bd->client.netwm.strut.bottom,
9854                                              &bd->client.netwm.strut.left_start_y,
9855                                              &bd->client.netwm.strut.left_end_y,
9856                                              &bd->client.netwm.strut.right_start_y,
9857                                              &bd->client.netwm.strut.right_end_y,
9858                                              &bd->client.netwm.strut.top_start_x,
9859                                              &bd->client.netwm.strut.top_end_x,
9860                                              &bd->client.netwm.strut.bottom_start_x,
9861                                              &bd->client.netwm.strut.bottom_end_x))
9862           {
9863              ecore_x_netwm_strut_get(bd->client.win,
9864                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
9865                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
9866
9867              bd->client.netwm.strut.left_start_y = 0;
9868              bd->client.netwm.strut.left_end_y = 0;
9869              bd->client.netwm.strut.right_start_y = 0;
9870              bd->client.netwm.strut.right_end_y = 0;
9871              bd->client.netwm.strut.top_start_x = 0;
9872              bd->client.netwm.strut.top_end_x = 0;
9873              bd->client.netwm.strut.bottom_start_x = 0;
9874              bd->client.netwm.strut.bottom_end_x = 0;
9875           }
9876         bd->client.netwm.fetch.strut = 0;
9877      }
9878    if (bd->client.qtopia.fetch.soft_menu)
9879      {
9880         e_hints_window_qtopia_soft_menu_get(bd);
9881         bd->client.qtopia.fetch.soft_menu = 0;
9882         rem_change = 1;
9883      }
9884    if (bd->client.qtopia.fetch.soft_menus)
9885      {
9886         e_hints_window_qtopia_soft_menus_get(bd);
9887         bd->client.qtopia.fetch.soft_menus = 0;
9888         rem_change = 1;
9889      }
9890    if (bd->client.vkbd.fetch.state)
9891      {
9892         e_hints_window_virtual_keyboard_state_get(bd);
9893         bd->client.vkbd.fetch.state = 0;
9894         rem_change = 1;
9895      }
9896    if (bd->client.vkbd.fetch.vkbd)
9897      {
9898         e_hints_window_virtual_keyboard_get(bd);
9899         bd->client.vkbd.fetch.vkbd = 0;
9900         rem_change = 1;
9901      }
9902    if (bd->client.illume.conformant.fetch.conformant)
9903      {
9904         bd->client.illume.conformant.conformant =
9905           ecore_x_e_illume_conformant_get(bd->client.win);
9906         bd->client.illume.conformant.fetch.conformant = 0;
9907      }
9908    if (bd->client.illume.quickpanel.fetch.state)
9909      {
9910         bd->client.illume.quickpanel.state =
9911           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
9912         bd->client.illume.quickpanel.fetch.state = 0;
9913      }
9914    if (bd->client.illume.quickpanel.fetch.quickpanel)
9915      {
9916         bd->client.illume.quickpanel.quickpanel =
9917           ecore_x_e_illume_quickpanel_get(bd->client.win);
9918         bd->client.illume.quickpanel.fetch.quickpanel = 0;
9919      }
9920    if (bd->client.illume.quickpanel.fetch.priority.major)
9921      {
9922         bd->client.illume.quickpanel.priority.major =
9923           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
9924         bd->client.illume.quickpanel.fetch.priority.major = 0;
9925      }
9926    if (bd->client.illume.quickpanel.fetch.priority.minor)
9927      {
9928         bd->client.illume.quickpanel.priority.minor =
9929           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
9930         bd->client.illume.quickpanel.fetch.priority.minor = 0;
9931      }
9932    if (bd->client.illume.quickpanel.fetch.zone)
9933      {
9934         bd->client.illume.quickpanel.zone =
9935           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
9936         bd->client.illume.quickpanel.fetch.zone = 0;
9937      }
9938    if (bd->client.illume.drag.fetch.drag)
9939      {
9940         bd->client.illume.drag.drag =
9941           ecore_x_e_illume_drag_get(bd->client.win);
9942         bd->client.illume.drag.fetch.drag = 0;
9943      }
9944    if (bd->client.illume.drag.fetch.locked)
9945      {
9946         bd->client.illume.drag.locked =
9947           ecore_x_e_illume_drag_locked_get(bd->client.win);
9948         bd->client.illume.drag.fetch.locked = 0;
9949      }
9950    if (bd->client.illume.win_state.fetch.state)
9951      {
9952         bd->client.illume.win_state.state =
9953            ecore_x_e_illume_window_state_get(bd->client.win);
9954         bd->client.illume.win_state.fetch.state = 0;
9955      }
9956    if (bd->changes.shape)
9957      {
9958         Ecore_X_Rectangle *rects;
9959         int num;
9960
9961         bd->changes.shape = 0;
9962         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
9963         if (rects)
9964           {
9965              int cw = 0, ch = 0;
9966
9967              /* This doesn't fix the race, but makes it smaller. we detect
9968               * this and if cw and ch != client w/h then mark this as needing
9969               * a shape change again to fixup next event loop.
9970               */
9971              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9972              if ((cw != bd->client.w) || (ch != bd->client.h))
9973                bd->changes.shape = 1;
9974              if ((num == 1) &&
9975                  (rects[0].x == 0) &&
9976                  (rects[0].y == 0) &&
9977                  ((int)rects[0].width == cw) &&
9978                  ((int)rects[0].height == ch))
9979                {
9980                   if (bd->client.shaped)
9981                     {
9982                        bd->client.shaped = 0;
9983                        if (!bd->bordername)
9984                          bd->client.border.changed = 1;
9985                     }
9986                }
9987              else
9988                {
9989                   if (!bd->client.shaped)
9990                     {
9991                        bd->client.shaped = 1;
9992                        if (!bd->bordername)
9993                          bd->client.border.changed = 1;
9994                     }
9995                }
9996              free(rects);
9997           }
9998         else
9999           {
10000              // FIXME: no rects i think can mean... totally empty window
10001              bd->client.shaped = 0;
10002              if (!bd->bordername)
10003                bd->client.border.changed = 1;
10004           }
10005         bd->need_shape_merge = 1;
10006      }
10007    if (bd->changes.shape_input)
10008      {
10009         Ecore_X_Rectangle *rects;
10010         int num;
10011
10012         bd->changes.shape_input = 0;
10013         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
10014         if (rects)
10015           {
10016              int cw = 0, ch = 0;
10017
10018              /* This doesn't fix the race, but makes it smaller. we detect
10019               * this and if cw and ch != client w/h then mark this as needing
10020               * a shape change again to fixup next event loop.
10021               */
10022              ecore_x_window_size_get(bd->client.win, &cw, &ch);
10023              if ((cw != bd->client.w) || (ch != bd->client.h))
10024                bd->changes.shape_input = 1;
10025              if ((num == 1) &&
10026                  (rects[0].x == 0) &&
10027                  (rects[0].y == 0) &&
10028                  ((int)rects[0].width == cw) &&
10029                  ((int)rects[0].height == ch))
10030                {
10031                   if (bd->shaped_input)
10032                     {
10033                        bd->shaped_input = 0;
10034                        if (!bd->bordername)
10035                          bd->client.border.changed = 1;
10036                     }
10037                }
10038              else
10039                {
10040                   if (!bd->shaped_input)
10041                     {
10042                        bd->shaped_input = 1;
10043                        if (!bd->bordername)
10044                          bd->client.border.changed = 1;
10045                     }
10046                }
10047              free(rects);
10048           }
10049         else
10050           {
10051              bd->shaped_input = 1;
10052              if (!bd->bordername)
10053                bd->client.border.changed = 1;
10054           }
10055         bd->need_shape_merge = 1;
10056      }
10057    if (bd->client.mwm.fetch.hints)
10058      {
10059         int pb;
10060
10061         bd->client.mwm.exists =
10062           ecore_x_mwm_hints_get(bd->client.win,
10063                                 &bd->client.mwm.func,
10064                                 &bd->client.mwm.decor,
10065                                 &bd->client.mwm.input);
10066         pb = bd->client.mwm.borderless;
10067         bd->client.mwm.borderless = 0;
10068         if (bd->client.mwm.exists)
10069           {
10070              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
10071                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
10072                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
10073                bd->client.mwm.borderless = 1;
10074           }
10075         if (bd->client.mwm.borderless != pb)
10076           {
10077              if ((!bd->lock_border) || (!bd->client.border.name))
10078                bd->client.border.changed = 1;
10079           }
10080         bd->client.mwm.fetch.hints = 0;
10081         rem_change = 1;
10082      }
10083    if (bd->client.e.fetch.video_parent)
10084      {
10085         /* unlinking child/parent */
10086         if (bd->client.e.state.video_parent_border != NULL)
10087           {
10088              bd->client.e.state.video_parent_border->client.e.state.video_child =
10089                eina_list_remove
10090                (bd->client.e.state.video_parent_border->client.e.state.video_child,
10091                    bd);
10092           }
10093
10094         ecore_x_window_prop_card32_get(bd->client.win,
10095                                        ECORE_X_ATOM_E_VIDEO_PARENT,
10096                                        &bd->client.e.state.video_parent,
10097                                        1);
10098
10099         /* linking child/parent */
10100         if (bd->client.e.state.video_parent != 0)
10101           {
10102              E_Border *tmp;
10103              Eina_List *l;
10104
10105              EINA_LIST_FOREACH(borders, l, tmp)
10106                if (tmp->client.win == bd->client.e.state.video_parent)
10107                  {
10108                     /* fprintf(stderr, "child added to parent \\o/\n"); */
10109                     bd->client.e.state.video_parent_border = tmp;
10110                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
10111                                                                        bd);
10112                     if (bd->desk != tmp->desk)
10113                       e_border_desk_set(bd, tmp->desk);
10114                     break;
10115                  }
10116           }
10117
10118         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
10119
10120         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
10121         rem_change = 1;
10122      }
10123    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
10124      {
10125         unsigned int xy[2];
10126
10127         ecore_x_window_prop_card32_get(bd->client.win,
10128                                        ECORE_X_ATOM_E_VIDEO_POSITION,
10129                                        xy,
10130                                        2);
10131         bd->client.e.state.video_position.x = xy[0];
10132         bd->client.e.state.video_position.y = xy[1];
10133         bd->client.e.state.video_position.updated = 1;
10134         bd->client.e.fetch.video_position = 0;
10135         bd->x = bd->client.e.state.video_position.x;
10136         bd->y = bd->client.e.state.video_position.y;
10137
10138         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
10139      }
10140    if (bd->client.netwm.update.state)
10141      {
10142         e_hints_window_state_set(bd);
10143         /* Some stats might change the border, like modal */
10144         if (((!bd->lock_border) || (!bd->client.border.name)) &&
10145             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10146           {
10147              bd->client.border.changed = 1;
10148           }
10149         if (bd->parent)
10150           {
10151              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10152                {
10153                   bd->parent->modal = bd;
10154                   if (bd->parent->focused)
10155                     e_border_focus_set(bd, 1, 1);
10156                }
10157           }
10158         else if (bd->leader)
10159           {
10160              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10161                {
10162                   bd->leader->modal = bd;
10163                   if (bd->leader->focused)
10164                     e_border_focus_set(bd, 1, 1);
10165                   else
10166                     {
10167                        Eina_List *l;
10168                        E_Border *child;
10169
10170                        EINA_LIST_FOREACH(bd->leader->group, l, child)
10171                          {
10172                             if ((child != bd) && (child->focused))
10173                               e_border_focus_set(bd, 1, 1);
10174                          }
10175                     }
10176                }
10177           }
10178         bd->client.netwm.update.state = 0;
10179      }
10180
10181    if (bd->new_client)
10182      {
10183         E_Event_Border_Add *ev;
10184         E_Exec_Instance *inst;
10185
10186         ev = E_NEW(E_Event_Border_Add, 1);
10187         ev->border = bd;
10188         e_object_ref(E_OBJECT(bd));
10189         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
10190         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
10191
10192         if ((!bd->lock_border) || (!bd->client.border.name))
10193           bd->client.border.changed = 1;
10194
10195           {
10196              char *str = NULL;
10197
10198              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
10199                  ((bd->client.icccm.client_leader > 0) &&
10200                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
10201                 )
10202                {
10203                   if (!strncmp(str, "E_START|", 8))
10204                     {
10205                        int id;
10206
10207                        id = atoi(str + 8);
10208                        if (id > 0) bd->client.netwm.startup_id = id;
10209                     }
10210                   free(str);
10211                }
10212           }
10213         /* It's ok not to have fetch flag, should only be set on startup
10214          *     * and not changed. */
10215         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
10216           {
10217              if (bd->client.icccm.client_leader)
10218                {
10219                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
10220                     bd->client.netwm.pid = -1;
10221                }
10222              else
10223                bd->client.netwm.pid = -1;
10224           }
10225
10226         if (!bd->re_manage)
10227           {
10228              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
10229                                                         bd->client.netwm.pid);
10230              if ((inst) && (inst->used == 0))
10231                {
10232                   E_Zone *zone;
10233                   E_Desk *desk;
10234
10235                   inst->used++;
10236                   zone = e_container_zone_number_get(bd->zone->container,
10237                                                      inst->screen);
10238                   if (zone) e_border_zone_set(bd, zone);
10239                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
10240                                           inst->desk_y);
10241                   if (desk) e_border_desk_set(bd, desk);
10242                   e_exec_instance_found(inst);
10243                }
10244
10245              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
10246                {
10247                   E_Border *bdl = NULL;
10248
10249                   bdl = bd->parent;
10250                   if (!bdl)
10251                     {
10252                        if (bd->leader) bdl = bd->leader;
10253                     }
10254                   if (!bdl)
10255                     {
10256                        E_Border *child;
10257                        E_Border_List *bl;
10258
10259                        bl = e_container_border_list_first(bd->zone->container);
10260                        while ((child = e_container_border_list_next(bl)))
10261                          {
10262                             if (child == bd) continue;
10263                             if (e_object_is_del(E_OBJECT(child))) continue;
10264                             if ((bd->client.icccm.client_leader) &&
10265                                 (child->client.icccm.client_leader ==
10266                                     bd->client.icccm.client_leader))
10267                               {
10268                                  bdl = child;
10269                                  break;
10270                               }
10271                          }
10272                        e_container_border_list_free(bl);
10273                     }
10274                   if (bdl)
10275                     {
10276                        if (bdl->zone)
10277                          e_border_zone_set(bd, bdl->zone);
10278                        if (bdl->desk)
10279                          e_border_desk_set(bd, bdl->desk);
10280                        else
10281                          e_border_stick(bd);
10282                     }
10283                }
10284           }
10285      }
10286
10287 #ifdef _F_USE_DESK_WINDOW_PROFILE_
10288    if (need_desk_set)
10289      {
10290         E_Container *con = bd->zone->container;
10291         E_Desk *desk = NULL;
10292         Eina_List *l;
10293         const char *str;
10294         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
10295           {
10296              desk = e_container_desk_window_profile_get(con, str);
10297              if (desk)
10298                {
10299                   if (bd->desk != desk)
10300                     {
10301                        bd->client.e.state.profile = eina_stringshare_add(str);
10302                        if (bd->zone != desk->zone)
10303                          e_border_zone_set(bd, desk->zone);
10304                        e_border_desk_set(bd, desk);
10305                     }
10306                   break;
10307                }
10308           }
10309      }
10310 #endif
10311
10312    /* PRE_POST_FETCH calls e_remember apply for new client */
10313    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
10314    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
10315    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
10316
10317 #ifdef _F_ZONE_WINDOW_ROTATION_
10318    if (e_config->wm_win_rotation)
10319      {
10320         if (need_rotation_set)
10321           {
10322              Eina_Bool hint = EINA_FALSE;
10323              int ang = 0;
10324              int x, y, w, h, move;
10325
10326              ELB(ELBT_ROT, "NEED ROT", bd->client.win);
10327              bd->client.e.state.rot.changes = _e_border_rotation_angle_get(bd);
10328
10329              if (bd->client.e.state.rot.changes == -1)
10330                {
10331                   ang = bd->client.e.state.rot.curr;
10332
10333                   hint = _e_border_rotation_geom_get(bd, bd->zone, ang, &x, &y, &w, &h, &move);
10334                   if (hint)
10335                     {
10336                        _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
10337                        ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
10338                             bd->client.icccm.name, x, y, w, h);
10339                     }
10340                }
10341              else bd->changed = 1;
10342           }
10343      }
10344 #endif
10345
10346    if (bd->need_reparent)
10347      {
10348         if (!bd->internal)
10349           ecore_x_window_save_set_add(bd->client.win);
10350         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
10351         if (bd->visible)
10352           {
10353              if ((bd->new_client) && (bd->internal) &&
10354                  (bd->internal_ecore_evas))
10355                ecore_evas_show(bd->internal_ecore_evas);
10356              ecore_x_window_show(bd->client.win);
10357           }
10358         bd->need_reparent = 0;
10359      }
10360
10361    if ((bd->client.border.changed) && (!bd->shaded) &&
10362        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10363      {
10364         const char *bordername;
10365
10366         if (bd->fullscreen)
10367           bordername = "borderless";
10368         else if (bd->bordername)
10369           bordername = bd->bordername;
10370         else if ((bd->client.mwm.borderless) || (bd->borderless))
10371           bordername = "borderless";
10372         else if (((bd->client.icccm.transient_for != 0) ||
10373                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
10374                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10375                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10376           bordername = "noresize_dialog";
10377         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10378                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10379           bordername = "noresize";
10380         else if (bd->client.shaped)
10381           bordername = "shaped";
10382         else if ((!bd->client.icccm.accepts_focus) &&
10383                  (!bd->client.icccm.take_focus))
10384           bordername = "nofocus";
10385         else if (bd->client.icccm.urgent)
10386           bordername = "urgent";
10387         else if ((bd->client.icccm.transient_for != 0) ||
10388                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10389           bordername = "dialog";
10390         else if (bd->client.netwm.state.modal)
10391           bordername = "modal";
10392         else if ((bd->client.netwm.state.skip_taskbar) ||
10393                  (bd->client.netwm.state.skip_pager))
10394           bordername = "skipped";
10395         else if ((bd->internal) && (bd->client.icccm.class) &&
10396                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
10397           bordername = "internal_fileman";
10398         else
10399           bordername = e_config->theme_default_border_style;
10400         if (!bordername) bordername = "default";
10401
10402         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
10403           {
10404              Evas_Object *o;
10405              char buf[4096];
10406              int ok;
10407
10408              bd->changes.border = 1;
10409              eina_stringshare_replace(&bd->client.border.name, bordername);
10410
10411              if (bd->bg_object)
10412                {
10413                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
10414                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
10415                   bd->changes.size = 1;
10416                   evas_object_del(bd->bg_object);
10417                }
10418              o = edje_object_add(bd->bg_evas);
10419              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
10420              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10421              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
10422                {
10423                   if (bd->client.border.name != e_config->theme_default_border_style)
10424                     {
10425                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
10426                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10427                     }
10428                   if (!ok)
10429                     {
10430                        ok = e_theme_edje_object_set(o, "base/theme/borders",
10431                                                     "e/widgets/border/default/border");
10432                        if (ok)
10433                          {
10434                             /* Reset default border style to default */
10435                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
10436                             e_config_save_queue();
10437                          }
10438                     }
10439                }
10440
10441              bd->shaped = 0;
10442              if (ok)
10443                {
10444                   const char *shape_option, *argb_option;
10445                   int use_argb = 0;
10446
10447                   bd->bg_object = o;
10448
10449                   if ((e_config->use_composite) && (!bd->client.argb))
10450                     {
10451                        argb_option = edje_object_data_get(o, "argb");
10452                        if ((argb_option) && (!strcmp(argb_option, "1")))
10453                          use_argb = 1;
10454
10455                        if (use_argb != bd->argb)
10456                          _e_border_frame_replace(bd, use_argb);
10457
10458                        o = bd->bg_object;
10459                     }
10460
10461                   if (!bd->argb)
10462                     {
10463                        shape_option = edje_object_data_get(o, "shaped");
10464                        if ((shape_option) && (!strcmp(shape_option, "1")))
10465                          bd->shaped = 1;
10466                     }
10467
10468                   if (bd->client.netwm.name)
10469                     edje_object_part_text_set(o, "e.text.title",
10470                                               bd->client.netwm.name);
10471                   else if (bd->client.icccm.title)
10472                     edje_object_part_text_set(o, "e.text.title",
10473                                               bd->client.icccm.title);
10474                }
10475              else
10476                {
10477                   evas_object_del(o);
10478                   bd->bg_object = NULL;
10479                }
10480
10481              _e_border_client_inset_calc(bd);
10482
10483              bd->w += (bd->client_inset.l + bd->client_inset.r);
10484              bd->h += (bd->client_inset.t + bd->client_inset.b);
10485              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
10486              bd->changes.size = 1;
10487              /*  really needed ? */
10488              ecore_x_window_move(bd->client.shell_win,
10489                                  bd->client_inset.l,
10490                                  bd->client_inset.t);
10491
10492              if (bd->maximized != E_MAXIMIZE_NONE)
10493                {
10494                   E_Maximize maximized = bd->maximized;
10495
10496                   /* to force possible resizes */
10497                   bd->maximized = E_MAXIMIZE_NONE;
10498
10499                   _e_border_maximize(bd, maximized);
10500
10501                   /* restore maximized state */
10502                   bd->maximized = maximized;
10503
10504                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
10505                                                bd->maximized & E_MAXIMIZE_VERTICAL);
10506                }
10507              if (bd->bg_object)
10508                {
10509                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
10510                                                   _e_border_cb_signal_bind, bd);
10511                   if (bd->focused)
10512                     {
10513                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
10514                        if (bd->icon_object)
10515                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10516                     }
10517                   if (bd->shaded)
10518                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
10519                   if (bd->sticky)
10520                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
10521                   if (bd->hung)
10522                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
10523                   // FIXME: in eval -do differently
10524                   //         edje_object_message_signal_process(bd->bg_object);
10525                   //         e_border_frame_recalc(bd);
10526
10527                   evas_object_move(bd->bg_object, 0, 0);
10528                   evas_object_resize(bd->bg_object, bd->w, bd->h);
10529                   evas_object_show(bd->bg_object);
10530                }
10531           }
10532         bd->client.border.changed = 0;
10533
10534         if (bd->icon_object)
10535           {
10536              if (bd->bg_object)
10537                {
10538                   evas_object_show(bd->icon_object);
10539                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10540                }
10541              else
10542                evas_object_hide(bd->icon_object);
10543           }
10544      }
10545
10546    if (rem_change) e_remember_update(bd);
10547
10548    if (change_urgent)
10549      {
10550         E_Event_Border_Urgent_Change *ev;
10551
10552         if (bd->client.icccm.urgent)
10553           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
10554         else
10555           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
10556
10557         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
10558         ev->border = bd;
10559         e_object_ref(E_OBJECT(bd));
10560         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
10561                         _e_border_event_border_urgent_change_free, NULL);
10562      }
10563
10564    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10565 }
10566
10567 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10568 static void
10569 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10570 {
10571    E_Border* temp_bd = NULL;
10572    E_Border* top_focusable_bd = NULL;
10573    Eina_Bool is_fully_obscured = EINA_FALSE;
10574    Ecore_X_XRegion *visible_region = NULL;
10575    Ecore_X_XRegion *win_region = NULL;
10576    Ecore_X_Rectangle visible_rect, win_rect;
10577    E_Border_List *bl;
10578
10579    // set the entire visible region as a root geometry
10580    visible_rect.x = bd->zone->x;
10581    visible_rect.y = bd->zone->y;
10582    visible_rect.width = bd->zone->w;
10583    visible_rect.height = bd->zone->h;
10584
10585    visible_region = ecore_x_xregion_new();
10586    if (!visible_region) return;
10587
10588    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10589
10590    bl = e_container_border_list_last(bd->zone->container);
10591    while ((temp_bd = e_container_border_list_prev(bl)))
10592      {
10593         if (temp_bd == bd) break;
10594
10595         if (temp_bd == focused) continue;
10596         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10597         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10598         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10599             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10600             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10601             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10602             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10603             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10604             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10605           {
10606              if (!top_focusable_bd)
10607                {
10608                   top_focusable_bd = temp_bd;
10609                }
10610
10611              win_rect.x = temp_bd->x;
10612              win_rect.y = temp_bd->y;
10613              win_rect.width = temp_bd->w;
10614              win_rect.height = temp_bd->h;
10615
10616              // if it stick out or is bigger than the entire visible region,
10617              // clip it by the entire visible's geometry.
10618              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10619                                   win_rect.width, win_rect.height,
10620                                   visible_rect.x, visible_rect.y,
10621                                   (int)(visible_rect.width), (int)(visible_rect.height));
10622
10623              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10624                {
10625                   win_region = ecore_x_xregion_new();
10626                   if (win_region)
10627                     {
10628                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10629                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10630                        ecore_x_xregion_free(win_region);
10631                        win_region = NULL;
10632
10633                        if (ecore_x_xregion_is_empty(visible_region))
10634                          {
10635                             is_fully_obscured = EINA_TRUE;
10636                             break;
10637                          }
10638                     }
10639                }
10640           }
10641      }
10642
10643    if (is_fully_obscured == EINA_TRUE)
10644      {
10645         e_border_focus_set(top_focusable_bd, 1, 1);
10646      }
10647    else
10648      {
10649         e_border_focus_set(bd, 1, 1);
10650      }
10651
10652    if (visible_region) ecore_x_xregion_free(visible_region);
10653    e_container_border_list_free(bl);
10654 }
10655
10656 static void
10657 _e_border_latest_stacked_focus(E_Border *bd)
10658 {
10659    E_Border *temp_bd;
10660    int root_w, root_h;
10661
10662    root_w = bd->zone->w;
10663    root_h = bd->zone->h;
10664
10665    Eina_List *l;
10666    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10667      {
10668         if (bd == temp_bd) continue;
10669         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10670         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10671
10672         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10673             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10674             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10675             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10676             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10677             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10678             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10679           {
10680              _e_border_latest_stacked_focus_check_set(temp_bd);
10681              break;
10682           }
10683      }
10684 }
10685
10686 static void
10687 _e_border_check_stack (E_Border *bd)
10688 {
10689    E_Border* temp_bd = NULL;
10690    E_Border* top_bd = NULL;
10691    int passed_focus = 0;
10692    int passed = 0;
10693    int root_w = bd->zone->w;
10694    int root_h = bd->zone->h;
10695
10696    E_Border_List *bl;
10697    bl = e_container_border_list_last(bd->zone->container);
10698    while ((temp_bd = e_container_border_list_prev(bl)))
10699      {
10700         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10701         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10702         if ((temp_bd != bd) &&
10703             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10704
10705         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10706            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10707            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10708            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10709            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10710            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10711            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10712           {
10713              if (bd == temp_bd)
10714                {
10715                   if (!passed)
10716                     {
10717                        e_border_focus_set_with_pointer(bd);
10718                        break;
10719                     }
10720                   else
10721                     {
10722                        if (!passed_focus)
10723                          {
10724                             e_border_focus_set_with_pointer(top_bd);
10725                          }
10726                        break;
10727                     }
10728                }
10729              else
10730                {
10731                   if (!passed)
10732                     {
10733                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10734                          {
10735                             if (!bd->lock_focus_out)
10736                               {
10737                                  e_border_focus_latest_set(bd);
10738                               }
10739                          }
10740                     }
10741                }
10742
10743              if (!passed)
10744                {
10745                   passed = 1;
10746                   top_bd = temp_bd;
10747                }
10748
10749              if (temp_bd == focused)
10750                {
10751                   passed_focus = 1;
10752                }
10753           }
10754      }
10755    e_container_border_list_free(bl);
10756 }
10757
10758 static void
10759 _e_border_focus_top_stack_set(E_Border* bd)
10760 {
10761    E_Border *temp_bd;
10762    int root_w, root_h;
10763
10764    root_w = bd->zone->w;
10765    root_h = bd->zone->h;
10766
10767    E_Border_List *bl;
10768    bl = e_container_border_list_last(bd->zone->container);
10769    while ((temp_bd = e_container_border_list_prev(bl)))
10770      {
10771         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10772         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10773         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
10774
10775         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10776            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10777            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10778            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10779            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10780            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10781            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10782           {
10783              if (!temp_bd->focused)
10784                {
10785                   /* this border is the top of the latest stack */
10786                   e_border_focus_set (temp_bd, 1, 1);
10787                }
10788              break;
10789           }
10790      }
10791    e_container_border_list_free(bl);
10792 }
10793 #endif
10794
10795 static void
10796 _e_border_eval(E_Border *bd)
10797 {
10798    E_Event_Border_Property *event;
10799    E_Border_Pending_Move_Resize *pnd;
10800    int rem_change = 0;
10801    int send_event = 1;
10802
10803    if (e_object_is_del(E_OBJECT(bd)))
10804      {
10805         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
10806         bd->changed = 0;
10807         return;
10808      }
10809
10810    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
10811
10812    if (bd->new_client)
10813      {
10814         int zx = 0, zy = 0, zw = 0, zh = 0;
10815
10816         if (bd->zone)
10817           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
10818
10819         /*
10820          * Limit maximum size of windows to useful geometry
10821          */
10822         // TODO: temoporary limited maximize algorithm
10823         // ->
10824         /*if (bd->w > zw)
10825           rw = zw;
10826           else
10827           rw = bd->w;
10828
10829           if (bd->h > zh)
10830           rh = zh;
10831           else
10832           rh = bd->h;
10833
10834           if ((rw != bd->w) || (rh != bd->h))
10835           {
10836           bd->w = rw;
10837           bd->h = rh;
10838           e_border_resize (bd, bd->w, bd->h);
10839           }*/
10840         // <-
10841
10842         if (bd->re_manage)
10843           {
10844              bd->x -= bd->client_inset.l;
10845              bd->y -= bd->client_inset.t;
10846              bd->changes.pos = 1;
10847              bd->placed = 1;
10848           }
10849         else if ((!bd->placed) && (bd->client.icccm.request_pos))
10850           {
10851
10852              Ecore_X_Window_Attributes *att;
10853              int bw;
10854
10855              att = &bd->client.initial_attributes;
10856              bw = att->border * 2;
10857              switch (bd->client.icccm.gravity)
10858                {
10859                 case ECORE_X_GRAVITY_N:
10860                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10861                    bd->y = att->y;
10862                    break;
10863
10864                 case ECORE_X_GRAVITY_NE:
10865                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10866                    bd->y = att->y;
10867                    break;
10868
10869                 case ECORE_X_GRAVITY_E:
10870                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10871                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10872                    break;
10873
10874                 case ECORE_X_GRAVITY_SE:
10875                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10876                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10877                    break;
10878
10879                 case ECORE_X_GRAVITY_S:
10880                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10881                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10882                    break;
10883
10884                 case ECORE_X_GRAVITY_SW:
10885                    bd->x = att->x;
10886                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10887                    break;
10888
10889                 case ECORE_X_GRAVITY_W:
10890                    bd->x = att->x;
10891                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10892                    break;
10893
10894                 case ECORE_X_GRAVITY_CENTER:
10895                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10896                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10897                    break;
10898
10899                 case ECORE_X_GRAVITY_NW:
10900                 default:
10901                    bd->x = att->x;
10902                    bd->y = att->y;
10903                }
10904
10905              /*
10906               * This ensures that windows that like to open with a x/y
10907               * position smaller than returned by e_zone_useful_geometry_get()
10908               * are moved to useful positions.
10909               */
10910              // ->
10911              if (e_config->geometry_auto_move)
10912                {
10913                   if (bd->x < zx)
10914                     bd->x = zx;
10915
10916                   if (bd->y < zy)
10917                     bd->y = zy;
10918
10919                   if (bd->x + bd->w > zx + zw)
10920                     bd->x = zx + zw - bd->w;
10921
10922                   if (bd->y + bd->h > zy + zh)
10923                     bd->y = zy + zh - bd->h;
10924                   // <--
10925
10926                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
10927                     {
10928                        bd->changes.pos = 1;
10929                        bd->placed = 1;
10930                     }
10931                }
10932              else
10933                {
10934                   bd->changes.pos = 1;
10935                   bd->placed = 1;
10936                }
10937           }
10938         if (!bd->placed)
10939           {
10940              /* FIXME: special placement for dialogs etc. etc. etc goes
10941               * here */
10942              /* FIXME: what if parent is not on this desktop - or zone? */
10943              if ((bd->parent) && (bd->parent->visible))
10944                {
10945                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
10946                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
10947                   bd->changes.pos = 1;
10948                   bd->placed = 1;
10949                }
10950 #if 0
10951              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10952                {
10953                   /* TODO: Place in center of group */
10954                }
10955 #endif
10956              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
10957                {
10958                   bd->x = zx + ((zw - bd->w) / 2);
10959                   bd->y = zy + ((zh - bd->h) / 2);
10960                   bd->changes.pos = 1;
10961                   bd->placed = 1;
10962                }
10963           }
10964         if (!bd->placed)
10965           {
10966              Eina_List *skiplist = NULL;
10967              int new_x, new_y;
10968
10969              if (zw > bd->w)
10970                new_x = zx + (rand() % (zw - bd->w));
10971              else
10972                new_x = zx;
10973              if (zh > bd->h)
10974                new_y = zy + (rand() % (zh - bd->h));
10975              else
10976                new_y = zy;
10977
10978              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
10979                {
10980                   skiplist = eina_list_append(skiplist, bd);
10981                   if (bd->desk)
10982                     e_place_desk_region_smart(bd->desk, skiplist,
10983                                               bd->x, bd->y, bd->w, bd->h,
10984                                               &new_x, &new_y);
10985                   else
10986                     e_place_zone_region_smart(bd->zone, skiplist,
10987                                               bd->x, bd->y, bd->w, bd->h,
10988                                               &new_x, &new_y);
10989                   eina_list_free(skiplist);
10990                }
10991              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
10992                {
10993                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
10994                                       &new_x, &new_y);
10995                }
10996              else
10997                {
10998                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
10999                                       bd->client_inset.t, &new_x, &new_y);
11000                }
11001              bd->x = new_x;
11002              bd->y = new_y;
11003              bd->changes.pos = 1;
11004           }
11005
11006         EINA_LIST_FREE(bd->pending_move_resize, pnd)
11007           {
11008              if ((!bd->lock_client_location) && (pnd->move))
11009                {
11010                   bd->x = pnd->x;
11011                   bd->y = pnd->y;
11012                   bd->changes.pos = 1;
11013                   bd->placed = 1;
11014                   if (pnd->without_border)
11015                     {
11016                        bd->x -= bd->client_inset.l;
11017                        bd->y -= bd->client_inset.t;
11018                     }
11019                }
11020              if ((!bd->lock_client_size) && (pnd->resize))
11021                {
11022                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
11023                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
11024                   bd->client.w = pnd->w;
11025                   bd->client.h = pnd->h;
11026                   bd->changes.size = 1;
11027                }
11028
11029              free(pnd);
11030           }
11031
11032         /* Recreate state */
11033         e_hints_window_init(bd);
11034         if ((bd->client.e.state.centered) &&
11035             ((!bd->remember) ||
11036              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
11037           {
11038              bd->x = zx + (zw - bd->w) / 2;
11039              bd->y = zy + (zh - bd->h) / 2;
11040              bd->changes.pos = 1;
11041              bd->placed = 1;
11042           }
11043
11044         _e_border_client_move_resize_send(bd);
11045
11046         /* if the explicit geometry request asks for the app to be
11047          * in another zone - well move it there */
11048         {
11049            E_Zone *zone;
11050
11051            zone = e_container_zone_at_point_get(bd->zone->container,
11052                                                 bd->x + (bd->w / 2),
11053                                                 bd->y + (bd->h / 2));
11054            if (!zone)
11055              zone = e_container_zone_at_point_get(bd->zone->container,
11056                                                   bd->x,
11057                                                   bd->y);
11058            if (!zone)
11059              zone = e_container_zone_at_point_get(bd->zone->container,
11060                                                   bd->x + bd->w - 1,
11061                                                   bd->y);
11062            if (!zone)
11063              zone = e_container_zone_at_point_get(bd->zone->container,
11064                                                   bd->x + bd->w - 1,
11065                                                   bd->y + bd->h - 1);
11066            if (!zone)
11067              zone = e_container_zone_at_point_get(bd->zone->container,
11068                                                   bd->x,
11069                                                   bd->y + bd->h - 1);
11070            if ((zone) && (zone != bd->zone))
11071              e_border_zone_set(bd, zone);
11072         }
11073      }
11074
11075    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
11076
11077    /* effect changes to the window border itself */
11078    if ((bd->changes.shading))
11079      {
11080         /*  show at start of unshade (but don't hide until end of shade) */
11081         if (bd->shaded)
11082           ecore_x_window_raise(bd->client.shell_win);
11083         bd->changes.shading = 0;
11084         rem_change = 1;
11085      }
11086    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
11087      {
11088         if (bd->shaded)
11089           ecore_x_window_lower(bd->client.shell_win);
11090         else
11091           ecore_x_window_raise(bd->client.shell_win);
11092         bd->changes.shaded = 0;
11093         rem_change = 1;
11094      }
11095    else if ((bd->changes.shaded) && (bd->changes.pos))
11096      {
11097         if (bd->shaded)
11098           ecore_x_window_lower(bd->client.shell_win);
11099         else
11100           ecore_x_window_raise(bd->client.shell_win);
11101         bd->changes.size = 1;
11102         bd->changes.shaded = 0;
11103         rem_change = 1;
11104      }
11105    else if ((bd->changes.shaded) && (bd->changes.size))
11106      {
11107         if (bd->shaded)
11108           ecore_x_window_lower(bd->client.shell_win);
11109         else
11110           ecore_x_window_raise(bd->client.shell_win);
11111         bd->changes.shaded = 0;
11112         rem_change = 1;
11113      }
11114    else if (bd->changes.shaded)
11115      {
11116         if (bd->shaded)
11117           ecore_x_window_lower(bd->client.shell_win);
11118         else
11119           ecore_x_window_raise(bd->client.shell_win);
11120         bd->changes.size = 1;
11121         bd->changes.shaded = 0;
11122         rem_change = 1;
11123      }
11124
11125    if (bd->changes.size)
11126      {
11127         int x = 0, y = 0, xx = 0, yy = 0;
11128
11129         if ((bd->shaded) && (!bd->shading))
11130           {
11131              evas_obscured_clear(bd->bg_evas);
11132           }
11133         else
11134           {
11135              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
11136              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
11137
11138              evas_obscured_clear(bd->bg_evas);
11139              evas_obscured_rectangle_add(bd->bg_evas,
11140                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
11141
11142              if (bd->shading)
11143                {
11144                   if (bd->shade.dir == E_DIRECTION_UP)
11145                     {
11146                        y = yy - bd->client.h;
11147                     }
11148                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11149                     {
11150                        x = xx - bd->client.w;
11151                     }
11152                }
11153           }
11154
11155         if (bd->client.e.state.video)
11156           {
11157              if (bd->client.e.state.video_position.updated)
11158                {
11159                   ecore_x_window_move(bd->win,
11160                                       bd->client.e.state.video_parent_border->x +
11161                                       bd->client.e.state.video_parent_border->client_inset.l +
11162                                       bd->client.e.state.video_parent_border->fx.x +
11163                                       bd->client.e.state.video_position.x,
11164                                       bd->client.e.state.video_parent_border->y +
11165                                       bd->client.e.state.video_parent_border->client_inset.t +
11166                                       bd->client.e.state.video_parent_border->fx.y +
11167                                       bd->client.e.state.video_position.y);
11168                   bd->client.e.state.video_position.updated = 0;
11169                }
11170           }
11171         else if (!bd->changes.pos)
11172           {
11173              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11174              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11175              bd->post_resize = 1;
11176           }
11177         else
11178           {
11179              E_Border *tmp;
11180              Eina_List *l;
11181
11182              ecore_x_window_move_resize(bd->win,
11183                                         bd->x + bd->fx.x,
11184                                         bd->y + bd->fx.y,
11185                                         bd->w, bd->h);
11186
11187              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
11188                ecore_x_window_move(tmp->win,
11189                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
11190                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
11191           }
11192
11193         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
11194
11195         if ((!bd->shaded) || (bd->shading))
11196           ecore_x_window_move_resize(bd->client.shell_win,
11197                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
11198
11199         if (bd->internal_ecore_evas)
11200           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
11201         else if (!bd->client.e.state.video)
11202           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
11203
11204         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
11205         evas_object_resize(bd->bg_object, bd->w, bd->h);
11206         e_container_shape_resize(bd->shape, bd->w, bd->h);
11207         if (bd->changes.pos)
11208           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11209
11210         _e_border_client_move_resize_send(bd);
11211
11212         bd->changes.pos = 0;
11213         bd->changes.size = 0;
11214         rem_change = 1;
11215      }
11216    else if (bd->changes.pos)
11217      {
11218         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11219         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11220         bd->post_move = 1;
11221
11222         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11223
11224         _e_border_client_move_resize_send(bd);
11225
11226         bd->changes.pos = 0;
11227         rem_change = 1;
11228      }
11229
11230    if (bd->changes.reset_gravity)
11231      {
11232         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
11233         bd->changes.reset_gravity = 0;
11234         rem_change = 1;
11235      }
11236
11237    if (bd->need_shape_merge)
11238      {
11239         _e_border_shape_input_rectangle_set(bd);
11240         if ((bd->shaped) || (bd->client.shaped))
11241           {
11242              Ecore_X_Window twin, twin2;
11243              int x, y;
11244
11245              twin = ecore_x_window_override_new
11246                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
11247              if (bd->shaped)
11248                ecore_x_window_shape_window_set(twin, bd->bg_win);
11249              else
11250                {
11251                   Ecore_X_Rectangle rects[4];
11252
11253                   rects[0].x = 0;
11254                   rects[0].y = 0;
11255                   rects[0].width = bd->w;
11256                   rects[0].height = bd->client_inset.t;
11257                   rects[1].x = 0;
11258                   rects[1].y = bd->client_inset.t;
11259                   rects[1].width = bd->client_inset.l;
11260                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11261                   rects[2].x = bd->w - bd->client_inset.r;
11262                   rects[2].y = bd->client_inset.t;
11263                   rects[2].width = bd->client_inset.r;
11264                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11265                   rects[3].x = 0;
11266                   rects[3].y = bd->h - bd->client_inset.b;
11267                   rects[3].width = bd->w;
11268                   rects[3].height = bd->client_inset.b;
11269                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
11270                }
11271              twin2 = ecore_x_window_override_new
11272                (bd->zone->container->scratch_win, 0, 0,
11273                 bd->w - bd->client_inset.l - bd->client_inset.r,
11274                 bd->h - bd->client_inset.t - bd->client_inset.b);
11275              x = 0;
11276              y = 0;
11277              if ((bd->shading) || (bd->shaded))
11278                {
11279                   if (bd->shade.dir == E_DIRECTION_UP)
11280                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
11281                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11282                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
11283                }
11284              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
11285                                                 x, y);
11286              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
11287                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
11288                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
11289              ecore_x_window_shape_window_add_xy(twin, twin2,
11290                                                 bd->client_inset.l,
11291                                                 bd->client_inset.t);
11292              ecore_x_window_free(twin2);
11293              ecore_x_window_shape_window_set(bd->win, twin);
11294              ecore_x_window_free(twin);
11295           }
11296         else
11297           ecore_x_window_shape_mask_set(bd->win, 0);
11298         //      bd->need_shape_export = 1;
11299         bd->need_shape_merge = 0;
11300      }
11301
11302    if (bd->need_shape_export)
11303      {
11304         Ecore_X_Rectangle *rects, *orects;
11305         int num;
11306
11307         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
11308         if (rects)
11309           {
11310              int changed;
11311
11312              changed = 1;
11313              if ((num == bd->shape_rects_num) && (bd->shape_rects))
11314                {
11315                   int i;
11316
11317                   orects = bd->shape_rects;
11318                   changed = 0;
11319                   for (i = 0; i < num; i++)
11320                     {
11321                        if (rects[i].x < 0)
11322                          {
11323                             rects[i].width -= rects[i].x;
11324                             rects[i].x = 0;
11325                          }
11326                        if ((rects[i].x + (int)rects[i].width) > bd->w)
11327                          rects[i].width = rects[i].width - rects[i].x;
11328                        if (rects[i].y < 0)
11329                          {
11330                             rects[i].height -= rects[i].y;
11331                             rects[i].y = 0;
11332                          }
11333                        if ((rects[i].y + (int)rects[i].height) > bd->h)
11334                          rects[i].height = rects[i].height - rects[i].y;
11335
11336                        if ((orects[i].x != rects[i].x) ||
11337                            (orects[i].y != rects[i].y) ||
11338                            (orects[i].width != rects[i].width) ||
11339                            (orects[i].height != rects[i].height))
11340                          {
11341                             changed = 1;
11342                             break;
11343                          }
11344                     }
11345                }
11346              if (changed)
11347                {
11348                   if (bd->client.shaped)
11349                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
11350                   else
11351                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
11352                   E_FREE(bd->shape_rects);
11353                   bd->shape_rects = rects;
11354                   bd->shape_rects_num = num;
11355                   e_container_shape_rects_set(bd->shape, rects, num);
11356                }
11357              else
11358                free(rects);
11359           }
11360         else
11361           {
11362              E_FREE(bd->shape_rects);
11363              bd->shape_rects = NULL;
11364              bd->shape_rects_num = 0;
11365              e_container_shape_rects_set(bd->shape, NULL, 0);
11366           }
11367         bd->need_shape_export = 0;
11368      }
11369
11370    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
11371      {
11372         int x, y;
11373
11374         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
11375         if ((!bd->placed) && (!bd->re_manage) &&
11376             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
11377             (!((bd->client.icccm.transient_for != 0) ||
11378                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
11379             (!bdmove) && (!bdresize))
11380           {
11381              /* Set this window into moving state */
11382
11383              bd->cur_mouse_action = e_action_find("window_move");
11384              if (bd->cur_mouse_action)
11385                {
11386                   if ((!bd->cur_mouse_action->func.end_mouse) &&
11387                       (!bd->cur_mouse_action->func.end))
11388                     bd->cur_mouse_action = NULL;
11389                   if (bd->cur_mouse_action)
11390                     {
11391                        bd->x = x - (bd->w >> 1);
11392                        bd->y = y - (bd->client_inset.t >> 1);
11393                        bd->changed = 1;
11394                        bd->changes.pos = 1;
11395
11396                        _e_border_client_move_resize_send(bd);
11397                     }
11398                }
11399           }
11400
11401         _e_border_show(bd);
11402
11403         if (bd->cur_mouse_action)
11404           {
11405              bd->moveinfo.down.x = bd->x + bd->fx.x;
11406              bd->moveinfo.down.y = bd->y + bd->fx.y;
11407              bd->moveinfo.down.w = bd->w;
11408              bd->moveinfo.down.h = bd->h;
11409              bd->mouse.current.mx = x;
11410              bd->mouse.current.my = y;
11411              bd->moveinfo.down.button = 0;
11412              bd->moveinfo.down.mx = x;
11413              bd->moveinfo.down.my = y;
11414
11415              grabbed = 1;
11416              e_object_ref(E_OBJECT(bd->cur_mouse_action));
11417              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
11418              if (e_config->border_raise_on_mouse_action)
11419                e_border_raise(bd);
11420              e_border_focus_set(bd, 1, 1);
11421           }
11422         bd->changes.visible = 0;
11423         rem_change = 1;
11424      }
11425
11426    if (bd->changes.icon)
11427      {
11428         if (bd->desktop)
11429           {
11430              efreet_desktop_free(bd->desktop);
11431              bd->desktop = NULL;
11432           }
11433         if (bd->icon_object)
11434           {
11435              evas_object_del(bd->icon_object);
11436              bd->icon_object = NULL;
11437           }
11438         if (bd->remember && bd->remember->prop.desktop_file)
11439           {
11440              const char *desktop = bd->remember->prop.desktop_file;
11441
11442              bd->desktop = efreet_desktop_get(desktop);
11443              if (!bd->desktop)
11444                bd->desktop = efreet_util_desktop_name_find(desktop);
11445           }
11446         if (!bd->desktop)
11447           {
11448              if ((bd->client.icccm.name) && (bd->client.icccm.class))
11449                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
11450                                                                bd->client.icccm.class);
11451           }
11452         if (!bd->desktop)
11453           {
11454              /* libreoffice and maybe others match window class
11455                 with .desktop file name */
11456              if (bd->client.icccm.class)
11457                {
11458                   char buf[128];
11459                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
11460                   bd->desktop = efreet_util_desktop_file_id_find(buf);
11461                }
11462           }
11463         if (!bd->desktop)
11464           {
11465              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
11466                                                       bd->client.netwm.pid);
11467              if (bd->desktop) efreet_desktop_ref(bd->desktop);
11468           }
11469         if (!bd->desktop && bd->client.icccm.name)
11470           {
11471              /* this works for most cases as fallback. useful when app is
11472                 run from a shell  */
11473              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
11474           }
11475         if (!bd->desktop && bd->client.icccm.transient_for)
11476           {
11477              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
11478              if (bd2 && bd2->desktop)
11479                {
11480                   efreet_desktop_ref(bd2->desktop);
11481                   bd->desktop = bd2->desktop;
11482                }
11483           }
11484         if (bd->desktop)
11485           {
11486              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
11487                                             bd->desktop->orig_path);
11488           }
11489
11490         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
11491         if ((bd->focused) && (bd->icon_object))
11492           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
11493         if (bd->bg_object)
11494           {
11495              evas_object_show(bd->icon_object);
11496              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
11497           }
11498         else
11499           evas_object_hide(bd->icon_object);
11500
11501         {
11502            E_Event_Border_Icon_Change *ev;
11503
11504            ev = E_NEW(E_Event_Border_Icon_Change, 1);
11505            ev->border = bd;
11506            e_object_ref(E_OBJECT(bd));
11507            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
11508            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
11509                            _e_border_event_border_icon_change_free, NULL);
11510         }
11511         bd->changes.icon = 0;
11512      }
11513
11514    bd->new_client = 0;
11515    bd->changed = 0;
11516    bd->changes.stack = 0;
11517    bd->changes.prop = 0;
11518
11519    if (bd->client.e.state.rot.changes != -1)
11520      {
11521         e_border_rotation_set(bd, bd->client.e.state.rot.changes);
11522         bd->client.e.state.rot.changes = -1;
11523      }
11524
11525    if ((bd->take_focus) || (bd->want_focus))
11526      {
11527         bd->take_focus = 0;
11528 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11529         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
11530             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
11531             (bd->want_focus))
11532 #else // original
11533         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
11534 #endif
11535           {
11536              bd->want_focus = 0;
11537 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11538              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
11539                 _e_border_check_stack(bd);
11540              else
11541 #endif
11542              e_border_focus_set_with_pointer(bd);
11543           }
11544         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11545           {
11546              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
11547                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
11548                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
11549                    e_border_focused_get())))
11550                {
11551                   e_border_focus_set_with_pointer(bd);
11552                }
11553           }
11554         else
11555           {
11556              /* focus window by default when it is the only one on desk */
11557              E_Border *bd2 = NULL;
11558              Eina_List *l;
11559              EINA_LIST_FOREACH(focus_stack, l, bd2)
11560                {
11561                   if (bd == bd2) continue;
11562                   if ((!bd2->iconic) && (bd2->visible) &&
11563                       ((bd->desk == bd2->desk) || bd2->sticky))
11564                     break;
11565                }
11566
11567              if (!bd2)
11568                {
11569                   e_border_focus_set_with_pointer(bd);
11570                }
11571           }
11572      }
11573
11574    if (bd->need_maximize)
11575      {
11576         E_Maximize max;
11577         max = bd->maximized;
11578         bd->maximized = E_MAXIMIZE_NONE;
11579         e_border_maximize(bd, max);
11580         bd->need_maximize = 0;
11581      }
11582
11583    if (bd->need_fullscreen)
11584      {
11585         e_border_fullscreen(bd, e_config->fullscreen_policy);
11586         bd->need_fullscreen = 0;
11587      }
11588
11589    if (rem_change)
11590      e_remember_update(bd);
11591
11592    if (send_event) // FIXME: send only if a property changed - above need to
11593      { // check on that. for now - always send.
11594         event = E_NEW(E_Event_Border_Property, 1);
11595         event->border = bd;
11596         e_object_ref(E_OBJECT(bd));
11597         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11598      }
11599    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11600 }
11601
11602 static void
11603 _e_border_moveinfo_gather(E_Border   *bd,
11604                           const char *source)
11605 {
11606    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11607    else if (e_util_glob_match(source, "mouse,*,2"))
11608      bd->moveinfo.down.button = 2;
11609    else if (e_util_glob_match(source, "mouse,*,3"))
11610      bd->moveinfo.down.button = 3;
11611    else bd->moveinfo.down.button = 0;
11612    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11613      {
11614         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11615         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11616      }
11617    else
11618      {
11619         bd->moveinfo.down.mx = bd->mouse.current.mx;
11620         bd->moveinfo.down.my = bd->mouse.current.my;
11621      }
11622 }
11623
11624 static void
11625 _e_border_resize_handle(E_Border *bd)
11626 {
11627    int x, y, w, h;
11628    int new_x, new_y, new_w, new_h;
11629    int tw, th;
11630    Eina_List *skiplist = NULL;
11631
11632    x = bd->x;
11633    y = bd->y;
11634    w = bd->w;
11635    h = bd->h;
11636
11637    if ((bd->resize_mode == RESIZE_TR) ||
11638        (bd->resize_mode == RESIZE_R) ||
11639        (bd->resize_mode == RESIZE_BR))
11640      {
11641         if ((bd->moveinfo.down.button >= 1) &&
11642             (bd->moveinfo.down.button <= 3))
11643           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11644             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11645         else
11646           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11647      }
11648    else if ((bd->resize_mode == RESIZE_TL) ||
11649             (bd->resize_mode == RESIZE_L) ||
11650             (bd->resize_mode == RESIZE_BL))
11651      {
11652         if ((bd->moveinfo.down.button >= 1) &&
11653             (bd->moveinfo.down.button <= 3))
11654           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11655             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11656         else
11657           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11658      }
11659
11660    if ((bd->resize_mode == RESIZE_TL) ||
11661        (bd->resize_mode == RESIZE_T) ||
11662        (bd->resize_mode == RESIZE_TR))
11663      {
11664         if ((bd->moveinfo.down.button >= 1) &&
11665             (bd->moveinfo.down.button <= 3))
11666           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11667             (bd->mouse.current.my - bd->moveinfo.down.my);
11668         else
11669           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11670      }
11671    else if ((bd->resize_mode == RESIZE_BL) ||
11672             (bd->resize_mode == RESIZE_B) ||
11673             (bd->resize_mode == RESIZE_BR))
11674      {
11675         if ((bd->moveinfo.down.button >= 1) &&
11676             (bd->moveinfo.down.button <= 3))
11677           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11678             (bd->mouse.current.my - bd->moveinfo.down.my);
11679         else
11680           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11681      }
11682
11683    tw = bd->w;
11684    th = bd->h;
11685
11686    if ((bd->resize_mode == RESIZE_TL) ||
11687        (bd->resize_mode == RESIZE_L) ||
11688        (bd->resize_mode == RESIZE_BL))
11689      x += (tw - w);
11690    if ((bd->resize_mode == RESIZE_TL) ||
11691        (bd->resize_mode == RESIZE_T) ||
11692        (bd->resize_mode == RESIZE_TR))
11693      y += (th - h);
11694
11695    skiplist = eina_list_append(skiplist, bd);
11696    e_resist_container_border_position(bd->zone->container, skiplist,
11697                                       bd->x, bd->y, bd->w, bd->h,
11698                                       x, y, w, h,
11699                                       &new_x, &new_y, &new_w, &new_h);
11700    eina_list_free(skiplist);
11701
11702    w = new_w;
11703    h = new_h;
11704    e_border_resize_limit(bd, &new_w, &new_h);
11705    if ((bd->resize_mode == RESIZE_TL) ||
11706        (bd->resize_mode == RESIZE_L) ||
11707        (bd->resize_mode == RESIZE_BL))
11708      new_x += (w - new_w);
11709    if ((bd->resize_mode == RESIZE_TL) ||
11710        (bd->resize_mode == RESIZE_T) ||
11711        (bd->resize_mode == RESIZE_TR))
11712      new_y += (h - new_h);
11713
11714    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11715 }
11716
11717 static Eina_Bool
11718 _e_border_shade_animator(void *data)
11719 {
11720    E_Border *bd = data;
11721    double dt, val;
11722    double dur = bd->client.h / e_config->border_shade_speed;
11723
11724    dt = ecore_loop_time_get() - bd->shade.start;
11725    val = dt / dur;
11726
11727    if (val < 0.0) val = 0.0;
11728    else if (val > 1.0) val = 1.0;
11729
11730    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11731      {
11732         bd->shade.val =
11733            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
11734         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11735      }
11736    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
11737      {
11738         bd->shade.val =
11739            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
11740         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11741      }
11742    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
11743      {
11744         bd->shade.val =
11745            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
11746         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11747      }
11748    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
11749      {
11750         bd->shade.val =
11751            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11752         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11753      }
11754    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
11755      {
11756         bd->shade.val =
11757            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
11758         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11759      }
11760    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
11761      {
11762         bd->shade.val =
11763            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
11764         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11765      }
11766    else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
11767      {
11768         bd->shade.val =
11769            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 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_BOUNCE)
11773      {
11774         bd->shade.val =
11775            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
11776         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11777      }
11778    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
11779      {
11780         bd->shade.val =
11781            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
11782         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11783      }
11784    else
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
11791    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
11792    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
11793    else if (bd->shade.val > .999)
11794      bd->shade.val = 1.0;
11795
11796    if (bd->shade.dir == E_DIRECTION_UP)
11797      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11798    else if (bd->shade.dir == E_DIRECTION_DOWN)
11799      {
11800         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11801         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
11802         bd->changes.pos = 1;
11803      }
11804    else if (bd->shade.dir == E_DIRECTION_LEFT)
11805      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11806    else if (bd->shade.dir == E_DIRECTION_RIGHT)
11807      {
11808         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11809         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
11810         bd->changes.pos = 1;
11811      }
11812
11813    if ((bd->shaped) || (bd->client.shaped))
11814      {
11815         bd->need_shape_merge = 1;
11816         bd->need_shape_export = 1;
11817      }
11818    if (bd->shaped_input)
11819      {
11820         bd->need_shape_merge = 1;
11821      }
11822    bd->changes.size = 1;
11823    bd->changed = 1;
11824
11825    /* we're done */
11826    if (val == 1)
11827      {
11828         E_Event_Border_Resize *ev;
11829
11830         bd->shading = 0;
11831         bd->shaded = !(bd->shaded);
11832         bd->changes.size = 1;
11833         bd->changes.shaded = 1;
11834         bd->changes.shading = 1;
11835         bd->changed = 1;
11836         bd->shade.anim = NULL;
11837
11838         if (bd->shaded)
11839           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
11840         else
11841           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
11842         edje_object_message_signal_process(bd->bg_object);
11843         e_border_frame_recalc(bd);
11844
11845         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
11846         ev = E_NEW(E_Event_Border_Resize, 1);
11847         ev->border = bd;
11848         e_object_ref(E_OBJECT(bd));
11849 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
11850         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
11851         return ECORE_CALLBACK_CANCEL;
11852      }
11853    return ECORE_CALLBACK_RENEW;
11854 }
11855
11856 static void
11857 _e_border_event_border_resize_free(void *data __UNUSED__,
11858                                    void      *ev)
11859 {
11860    E_Event_Border_Resize *e;
11861
11862    e = ev;
11863 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
11864    e_object_unref(E_OBJECT(e->border));
11865    E_FREE(e);
11866 }
11867
11868 static void
11869 _e_border_event_border_move_free(void *data __UNUSED__,
11870                                  void      *ev)
11871 {
11872    E_Event_Border_Move *e;
11873
11874    e = ev;
11875 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
11876    e_object_unref(E_OBJECT(e->border));
11877    E_FREE(e);
11878 }
11879
11880 static void
11881 _e_border_event_border_add_free(void *data __UNUSED__,
11882                                 void      *ev)
11883 {
11884    E_Event_Border_Add *e;
11885
11886    e = ev;
11887 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
11888    e_object_unref(E_OBJECT(e->border));
11889    E_FREE(e);
11890 }
11891
11892 static void
11893 _e_border_event_border_remove_free(void *data __UNUSED__,
11894                                    void      *ev)
11895 {
11896    E_Event_Border_Remove *e;
11897
11898    e = ev;
11899 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
11900    e_object_unref(E_OBJECT(e->border));
11901    E_FREE(e);
11902 }
11903
11904 static void
11905 _e_border_event_border_show_free(void *data __UNUSED__,
11906                                  void      *ev)
11907 {
11908    E_Event_Border_Show *e;
11909
11910    e = ev;
11911 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
11912    e_object_unref(E_OBJECT(e->border));
11913    E_FREE(e);
11914 }
11915
11916 static void
11917 _e_border_event_border_hide_free(void *data __UNUSED__,
11918                                  void      *ev)
11919 {
11920    E_Event_Border_Hide *e;
11921
11922    e = ev;
11923 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
11924    e_object_unref(E_OBJECT(e->border));
11925    E_FREE(e);
11926 }
11927
11928 static void
11929 _e_border_event_border_iconify_free(void *data __UNUSED__,
11930                                     void      *ev)
11931 {
11932    E_Event_Border_Iconify *e;
11933
11934    e = ev;
11935 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
11936    e_object_unref(E_OBJECT(e->border));
11937    E_FREE(e);
11938 }
11939
11940 static void
11941 _e_border_event_border_uniconify_free(void *data __UNUSED__,
11942                                       void      *ev)
11943 {
11944    E_Event_Border_Uniconify *e;
11945
11946    e = ev;
11947 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
11948    e_object_unref(E_OBJECT(e->border));
11949    E_FREE(e);
11950 }
11951
11952 static void
11953 _e_border_event_border_stick_free(void *data __UNUSED__,
11954                                   void      *ev)
11955 {
11956    E_Event_Border_Stick *e;
11957
11958    e = ev;
11959 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
11960    e_object_unref(E_OBJECT(e->border));
11961    E_FREE(e);
11962 }
11963
11964 static void
11965 _e_border_event_border_unstick_free(void *data __UNUSED__,
11966                                     void      *ev)
11967 {
11968    E_Event_Border_Unstick *e;
11969
11970    e = ev;
11971 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
11972    e_object_unref(E_OBJECT(e->border));
11973    E_FREE(e);
11974 }
11975
11976 static void
11977 _e_border_event_border_zone_set_free(void *data __UNUSED__,
11978                                      void      *ev)
11979 {
11980    E_Event_Border_Zone_Set *e;
11981
11982    e = ev;
11983 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
11984    e_object_unref(E_OBJECT(e->border));
11985    e_object_unref(E_OBJECT(e->zone));
11986    E_FREE(e);
11987 }
11988
11989 static void
11990 _e_border_event_border_desk_set_free(void *data __UNUSED__,
11991                                      void      *ev)
11992 {
11993    E_Event_Border_Desk_Set *e;
11994
11995    e = ev;
11996 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
11997    e_object_unref(E_OBJECT(e->border));
11998    e_object_unref(E_OBJECT(e->desk));
11999    E_FREE(e);
12000 }
12001
12002 static void
12003 _e_border_event_border_stack_free(void *data __UNUSED__,
12004                                   void      *ev)
12005 {
12006    E_Event_Border_Stack *e;
12007
12008    e = ev;
12009 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
12010    e_object_unref(E_OBJECT(e->border));
12011    if (e->stack)
12012      {
12013 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
12014           e_object_unref(E_OBJECT(e->stack));
12015      }
12016    E_FREE(e);
12017 }
12018
12019 static void
12020 _e_border_event_border_icon_change_free(void *data __UNUSED__,
12021                                         void      *ev)
12022 {
12023    E_Event_Border_Icon_Change *e;
12024
12025    e = ev;
12026 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
12027    e_object_unref(E_OBJECT(e->border));
12028    E_FREE(e);
12029 }
12030
12031 static void
12032 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
12033                                           void      *ev)
12034 {
12035    E_Event_Border_Urgent_Change *e;
12036
12037    e = ev;
12038    e_object_unref(E_OBJECT(e->border));
12039    E_FREE(e);
12040 }
12041
12042 static void
12043 _e_border_event_border_focus_in_free(void *data __UNUSED__,
12044                                      void      *ev)
12045 {
12046    E_Event_Border_Focus_In *e;
12047
12048    e = ev;
12049    e_object_unref(E_OBJECT(e->border));
12050    E_FREE(e);
12051 }
12052
12053 static void
12054 _e_border_event_border_focus_out_free(void *data __UNUSED__,
12055                                       void      *ev)
12056 {
12057    E_Event_Border_Focus_Out *e;
12058
12059    e = ev;
12060    e_object_unref(E_OBJECT(e->border));
12061    E_FREE(e);
12062 }
12063
12064 static void
12065 _e_border_event_border_property_free(void *data __UNUSED__,
12066                                      void      *ev)
12067 {
12068    E_Event_Border_Property *e;
12069
12070    e = ev;
12071    e_object_unref(E_OBJECT(e->border));
12072    E_FREE(e);
12073 }
12074
12075 static void
12076 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
12077                                        void      *ev)
12078 {
12079    E_Event_Border_Fullscreen *e;
12080
12081    e = ev;
12082 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
12083    e_object_unref(E_OBJECT(e->border));
12084    E_FREE(e);
12085 }
12086
12087 static void
12088 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
12089                                          void      *ev)
12090 {
12091    E_Event_Border_Unfullscreen *e;
12092
12093    e = ev;
12094 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
12095    e_object_unref(E_OBJECT(e->border));
12096    E_FREE(e);
12097 }
12098
12099 #ifdef _F_ZONE_WINDOW_ROTATION_
12100 static void
12101 _e_border_event_border_rotation_change_begin_free(void *data __UNUSED__,
12102                                                   void      *ev)
12103 {
12104    E_Event_Border_Rotation_Change_Begin *e;
12105    e = ev;
12106    e_object_unref(E_OBJECT(e->border));
12107    E_FREE(e);
12108 }
12109
12110 static void
12111 _e_border_event_border_rotation_change_cancel_free(void *data __UNUSED__,
12112                                                    void      *ev)
12113 {
12114    E_Event_Border_Rotation_Change_Cancel *e;
12115    e = ev;
12116    e_object_unref(E_OBJECT(e->border));
12117    E_FREE(e);
12118 }
12119
12120 static void
12121 _e_border_event_border_rotation_change_end_free(void *data __UNUSED__,
12122                                                 void      *ev)
12123 {
12124    E_Event_Border_Rotation_Change_End *e;
12125    e = ev;
12126    e_object_unref(E_OBJECT(e->border));
12127    E_FREE(e);
12128 }
12129
12130 static void
12131 _e_border_event_border_rotation_change_begin_send(E_Border *bd)
12132 {
12133    E_Event_Border_Rotation_Change_Begin *ev = NULL;
12134    ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
12135    if (ev)
12136      {
12137         ev->border = bd;
12138         e_object_ref(E_OBJECT(bd));
12139         ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_BEGIN,
12140                         ev,
12141                         _e_border_event_border_rotation_change_begin_free,
12142                         NULL);
12143      }
12144 }
12145 #endif
12146
12147 static void
12148 _e_border_zone_update(E_Border *bd)
12149 {
12150    E_Container *con;
12151    Eina_List *l;
12152    E_Zone *zone;
12153
12154    /* still within old zone - leave it there */
12155    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12156                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
12157 #if _F_BORDER_CLIP_TO_ZONE_
12158      {
12159         _e_border_shape_input_clip_to_zone(bd);
12160         return;
12161      }
12162 #else
12163      return;
12164 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12165    /* find a new zone */
12166    con = bd->zone->container;
12167    EINA_LIST_FOREACH(con->zones, l, zone)
12168      {
12169         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12170                          zone->x, zone->y, zone->w, zone->h))
12171           {
12172              e_border_zone_set(bd, zone);
12173 #if _F_BORDER_CLIP_TO_ZONE_
12174              _e_border_shape_input_clip_to_zone(bd);
12175 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12176              return;
12177           }
12178      }
12179 }
12180
12181 static int
12182 _e_border_resize_begin(E_Border *bd)
12183 {
12184    int ret;
12185
12186    if (!bd->lock_user_stacking)
12187      {
12188         if (e_config->border_raise_on_mouse_action)
12189           e_border_raise(bd);
12190      }
12191    if ((bd->shaded) || (bd->shading) ||
12192        (bd->fullscreen) || (bd->lock_user_size))
12193      return 0;
12194
12195    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12196      ret = e_grabinput_get(bd->win, 0, bd->win);
12197    else
12198      ret = e_grabinput_get(bd->win, 0, 0);
12199
12200    if (grabbed && !ret)
12201      {
12202         grabbed = 0;
12203         return 0;
12204      }
12205
12206    if (bd->client.netwm.sync.request)
12207      {
12208         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12209         bd->client.netwm.sync.serial = 1;
12210         bd->client.netwm.sync.wait = 0;
12211         bd->client.netwm.sync.send_time = ecore_loop_time_get();
12212      }
12213
12214    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
12215
12216    bdresize = bd;
12217    return 1;
12218 }
12219
12220 static int
12221 _e_border_resize_end(E_Border *bd)
12222 {
12223    if (grabbed)
12224      {
12225         e_grabinput_release(bd->win, bd->win);
12226         grabbed = 0;
12227      }
12228    if (bd->client.netwm.sync.alarm)
12229      {
12230         E_Border_Pending_Move_Resize *pnd;
12231
12232         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12233         bd->client.netwm.sync.alarm = 0;
12234         /* resize to last geometry if sync alarm for it was not yet handled */
12235         if (bd->pending_move_resize)
12236           {
12237              bd->changed = 1;
12238              bd->changes.pos = 1;
12239              bd->changes.size = 1;
12240              _e_border_client_move_resize_send(bd);
12241           }
12242
12243         EINA_LIST_FREE(bd->pending_move_resize, pnd)
12244           E_FREE(pnd);
12245      }
12246
12247    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
12248
12249    bdresize = NULL;
12250
12251    /* If this border was maximized, we need to unset Maximized state or
12252     * on restart, E still thinks it's maximized */
12253    if (bd->maximized != E_MAXIMIZE_NONE)
12254      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
12255                                   bd->maximized & E_MAXIMIZE_NONE);
12256    return 1;
12257 }
12258
12259 static void
12260 _e_border_resize_update(E_Border *bd)
12261 {
12262    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
12263 }
12264
12265 static int
12266 _e_border_move_begin(E_Border *bd)
12267 {
12268    int ret;
12269    if (!bd->lock_user_stacking)
12270      {
12271         if (e_config->border_raise_on_mouse_action)
12272           e_border_raise(bd);
12273      }
12274    if ((bd->fullscreen) || (bd->lock_user_location))
12275      return 0;
12276
12277    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12278      ret = e_grabinput_get(bd->win, 0, bd->win);
12279    else
12280      ret = e_grabinput_get(bd->win, 0, 0);
12281
12282    if (grabbed && !ret)
12283      {
12284         grabbed = 0;
12285         return 0;
12286      }
12287 #if 0
12288    if (bd->client.netwm.sync.request)
12289      {
12290         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12291         bd->client.netwm.sync.serial = 0;
12292         bd->client.netwm.sync.wait = 0;
12293         bd->client.netwm.sync.time = ecore_loop_time_get();
12294      }
12295 #endif
12296    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
12297
12298    bdmove = bd;
12299    return 1;
12300 }
12301
12302 static int
12303 _e_border_move_end(E_Border *bd)
12304 {
12305    if (grabbed)
12306      {
12307         e_grabinput_release(bd->win, bd->win);
12308         grabbed = 0;
12309      }
12310 #if 0
12311    if (bd->client.netwm.sync.alarm)
12312      {
12313         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12314         bd->client.netwm.sync.alarm = 0;
12315      }
12316 #endif
12317    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
12318
12319    bdmove = NULL;
12320    return 1;
12321 }
12322
12323 static void
12324 _e_border_move_update(E_Border *bd)
12325 {
12326    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
12327 }
12328
12329 static Eina_Bool
12330 _e_border_cb_ping_poller(void *data)
12331 {
12332    E_Border *bd;
12333
12334    bd = data;
12335    if (bd->ping_ok)
12336      {
12337         if (bd->hung)
12338           {
12339              bd->hung = 0;
12340              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
12341              if (bd->kill_timer)
12342                {
12343                   ecore_timer_del(bd->kill_timer);
12344                   bd->kill_timer = NULL;
12345                }
12346           }
12347      }
12348    else
12349      {
12350         /* if time between last ping and now is greater
12351          * than half the ping interval... */
12352         if ((ecore_loop_time_get() - bd->ping) >
12353             ((e_config->ping_clients_interval *
12354               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
12355           {
12356              if (!bd->hung)
12357                {
12358                   bd->hung = 1;
12359                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
12360                   /* FIXME: if below dialog is up - hide it now */
12361                }
12362              if (bd->delete_requested)
12363                {
12364                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
12365                   e_border_act_kill_begin(bd);
12366                }
12367           }
12368      }
12369    bd->ping_poller = NULL;
12370    e_border_ping(bd);
12371    return ECORE_CALLBACK_CANCEL;
12372 }
12373
12374 static Eina_Bool
12375 _e_border_cb_kill_timer(void *data)
12376 {
12377    E_Border *bd;
12378
12379    bd = data;
12380 // dont wait until it's hung -
12381 //   if (bd->hung)
12382 //     {
12383         if (bd->client.netwm.pid > 1)
12384           kill(bd->client.netwm.pid, SIGKILL);
12385 //     }
12386    bd->kill_timer = NULL;
12387    return ECORE_CALLBACK_CANCEL;
12388 }
12389
12390 static void
12391 _e_border_pointer_resize_begin(E_Border *bd)
12392 {
12393    switch (bd->resize_mode)
12394      {
12395       case RESIZE_TL:
12396         e_pointer_type_push(bd->pointer, bd, "resize_tl");
12397         break;
12398
12399       case RESIZE_T:
12400         e_pointer_type_push(bd->pointer, bd, "resize_t");
12401         break;
12402
12403       case RESIZE_TR:
12404         e_pointer_type_push(bd->pointer, bd, "resize_tr");
12405         break;
12406
12407       case RESIZE_R:
12408         e_pointer_type_push(bd->pointer, bd, "resize_r");
12409         break;
12410
12411       case RESIZE_BR:
12412         e_pointer_type_push(bd->pointer, bd, "resize_br");
12413         break;
12414
12415       case RESIZE_B:
12416         e_pointer_type_push(bd->pointer, bd, "resize_b");
12417         break;
12418
12419       case RESIZE_BL:
12420         e_pointer_type_push(bd->pointer, bd, "resize_bl");
12421         break;
12422
12423       case RESIZE_L:
12424         e_pointer_type_push(bd->pointer, bd, "resize_l");
12425         break;
12426      }
12427 }
12428
12429 static void
12430 _e_border_pointer_resize_end(E_Border *bd)
12431 {
12432    switch (bd->resize_mode)
12433      {
12434       case RESIZE_TL:
12435         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
12436         break;
12437
12438       case RESIZE_T:
12439         e_pointer_type_pop(bd->pointer, bd, "resize_t");
12440         break;
12441
12442       case RESIZE_TR:
12443         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
12444         break;
12445
12446       case RESIZE_R:
12447         e_pointer_type_pop(bd->pointer, bd, "resize_r");
12448         break;
12449
12450       case RESIZE_BR:
12451         e_pointer_type_pop(bd->pointer, bd, "resize_br");
12452         break;
12453
12454       case RESIZE_B:
12455         e_pointer_type_pop(bd->pointer, bd, "resize_b");
12456         break;
12457
12458       case RESIZE_BL:
12459         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
12460         break;
12461
12462       case RESIZE_L:
12463         e_pointer_type_pop(bd->pointer, bd, "resize_l");
12464         break;
12465      }
12466 }
12467
12468 static void
12469 _e_border_pointer_move_begin(E_Border *bd)
12470 {
12471    e_pointer_type_push(bd->pointer, bd, "move");
12472 }
12473
12474 static void
12475 _e_border_pointer_move_end(E_Border *bd)
12476 {
12477    e_pointer_type_pop(bd->pointer, bd, "move");
12478 }
12479
12480 static Eina_List *_e_border_hooks = NULL;
12481 static int _e_border_hooks_delete = 0;
12482 static int _e_border_hooks_walking = 0;
12483
12484 static void
12485 _e_border_hooks_clean(void)
12486 {
12487    Eina_List *l, *ln;
12488    E_Border_Hook *bh;
12489
12490    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
12491      {
12492         if (bh->delete_me)
12493           {
12494              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
12495              free(bh);
12496           }
12497      }
12498 }
12499
12500 static void
12501 _e_border_hook_call(E_Border_Hook_Point hookpoint,
12502                     void               *bd)
12503 {
12504    Eina_List *l;
12505    E_Border_Hook *bh;
12506
12507    _e_border_hooks_walking++;
12508    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
12509      {
12510         if (bh->delete_me) continue;
12511         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
12512      }
12513    _e_border_hooks_walking--;
12514    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
12515      _e_border_hooks_clean();
12516 }
12517
12518 EAPI E_Border_Hook *
12519 e_border_hook_add(E_Border_Hook_Point               hookpoint,
12520                   void                              (*func)(void *data,
12521                                               void *bd),
12522                   void                             *data)
12523 {
12524    E_Border_Hook *bh;
12525
12526    bh = E_NEW(E_Border_Hook, 1);
12527    if (!bh) return NULL;
12528    bh->hookpoint = hookpoint;
12529    bh->func = func;
12530    bh->data = data;
12531    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
12532    return bh;
12533 }
12534
12535 EAPI void
12536 e_border_hook_del(E_Border_Hook *bh)
12537 {
12538    bh->delete_me = 1;
12539    if (_e_border_hooks_walking == 0)
12540      {
12541         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
12542         free(bh);
12543      }
12544    else
12545      _e_border_hooks_delete++;
12546 }
12547
12548 EAPI void
12549 e_border_focus_track_freeze(void)
12550 {
12551    focus_track_frozen++;
12552 }
12553
12554 EAPI void
12555 e_border_focus_track_thaw(void)
12556 {
12557    focus_track_frozen--;
12558 }
12559
12560 EAPI E_Border *
12561 e_border_under_pointer_get(E_Desk   *desk,
12562                            E_Border *exclude)
12563 {
12564    E_Border *bd = NULL, *cbd;
12565    Eina_List *l;
12566    int x, y;
12567
12568    /* We need to ensure that we can get the container window for the
12569     * zone of either the given desk or the desk of the excluded
12570     * window, so return if neither is given */
12571    if (desk)
12572      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
12573    else if (exclude)
12574      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
12575    else
12576      return NULL;
12577
12578    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
12579      {
12580         if (!cbd) continue;
12581         /* If a border was specified which should be excluded from the list
12582          * (because it will be closed shortly for example), skip */
12583         if ((exclude) && (cbd == exclude)) continue;
12584         if ((desk) && (cbd->desk != desk)) continue;
12585         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
12586           continue;
12587         /* If the layer is higher, the position of the window is higher
12588          * (always on top vs always below) */
12589         if (!bd || (cbd->layer > bd->layer))
12590           {
12591              bd = cbd;
12592              break;
12593           }
12594      }
12595    return bd;
12596 }
12597
12598 static Eina_Bool
12599 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
12600 {
12601    if (warp_to)
12602      {
12603         int x, y;
12604         double spd;
12605
12606         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
12607         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
12608             (y - warp_y) > 5 || (y - warp_y) < -5)
12609           {
12610              /* User moved the mouse, so stop warping */
12611              warp_to = 0;
12612              goto cleanup;
12613           }
12614
12615         /* We just use the same warp speed as configured
12616          * for the windowlist */
12617         spd = e_config->winlist_warp_speed;
12618         x = warp_x;
12619         y = warp_y;
12620         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12621         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12622         if (warp_x == x && warp_y == y)
12623           {
12624              warp_x = warp_to_x;
12625              warp_y = warp_to_y;
12626              warp_to = 0;
12627              goto cleanup;
12628           }
12629         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12630         return ECORE_CALLBACK_RENEW;
12631      }
12632  cleanup:
12633    ecore_timer_del(warp_timer);
12634    warp_timer = NULL;
12635    return ECORE_CALLBACK_CANCEL;
12636 }
12637
12638 EAPI int
12639 e_border_pointer_warp_to_center(E_Border *bd)
12640 {
12641    int x, y;
12642
12643    /* Do not slide pointer when disabled (probably breaks focus
12644     * on sloppy/mouse focus but requested by users). */
12645    if (!e_config->pointer_slide) return 0;
12646    /* Only warp the pointer if it is not already in the area of
12647     * the given border */
12648    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12649    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12650        (y >= bd->y) && (y <= (bd->y + bd->h)))
12651      return 0;
12652
12653    warp_to_x = bd->x + (bd->w / 2);
12654    if (warp_to_x < (bd->zone->x + 1))
12655      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12656    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12657      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12658
12659    warp_to_y = bd->y + (bd->h / 2);
12660    if (warp_to_y < (bd->zone->y + 1))
12661      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12662    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12663      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12664
12665    warp_to = 1;
12666    warp_to_win = bd->zone->container->win;
12667    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12668    if (!warp_timer)
12669      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12670    return 1;
12671 }
12672
12673 EAPI void
12674 e_border_comp_hidden_set(E_Border *bd,
12675                          Eina_Bool hidden)
12676 {
12677    E_Border *tmp;
12678    Eina_List *l;
12679
12680    E_OBJECT_CHECK(bd);
12681    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12682
12683    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12684      {
12685        if (hidden)
12686          ecore_x_window_hide(tmp->win);
12687        else
12688          ecore_x_window_show(tmp->win);
12689      }
12690
12691    if (bd->comp_hidden == hidden) return;
12692
12693    bd->comp_hidden = hidden;
12694
12695    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12696      {
12697         ecore_x_composite_window_events_disable(bd->win);
12698         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12699      }
12700    else
12701      {
12702         _e_border_shape_input_rectangle_set(bd);
12703         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12704      }
12705 }
12706
12707 EAPI void
12708 e_border_tmp_input_hidden_push(E_Border *bd)
12709 {
12710    E_Border *tmp;
12711    Eina_List *l;
12712
12713    E_OBJECT_CHECK(bd);
12714    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12715
12716    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12717      e_border_tmp_input_hidden_push(tmp);
12718
12719    bd->tmp_input_hidden++;
12720    if (bd->tmp_input_hidden != 1) return;
12721
12722    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12723      {
12724         ecore_x_composite_window_events_disable(bd->win);
12725         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12726      }
12727    else
12728      {
12729         _e_border_shape_input_rectangle_set(bd);
12730         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12731      }
12732 }
12733
12734 EAPI void
12735 e_border_tmp_input_hidden_pop(E_Border *bd)
12736 {
12737    E_Border *tmp;
12738    Eina_List *l;
12739
12740    E_OBJECT_CHECK(bd);
12741    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12742
12743    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12744      e_border_tmp_input_hidden_pop(tmp);
12745
12746    bd->tmp_input_hidden--;
12747    if (bd->tmp_input_hidden != 0) return;
12748
12749    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12750      {
12751         ecore_x_composite_window_events_disable(bd->win);
12752         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12753      }
12754    else
12755      {
12756         _e_border_shape_input_rectangle_set(bd);
12757         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12758      }
12759 }
12760
12761 EAPI void
12762 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
12763 {
12764    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
12765        ((bd->parent) &&
12766         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
12767          ((bd->parent->focused) &&
12768           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
12769        (just_do_it))
12770      {
12771         if (bd->iconic)
12772           {
12773              if (e_config->clientlist_warp_to_iconified_desktop == 1)
12774                e_desk_show(bd->desk);
12775              
12776              if (!bd->lock_user_iconify)
12777                e_border_uniconify(bd);
12778           }
12779         if ((!bd->iconic) && (!bd->sticky))
12780           e_desk_show(bd->desk);
12781         if (!bd->lock_user_stacking) e_border_raise(bd);
12782         if (!bd->lock_focus_out)
12783           {
12784              /* XXX ooffice does send this request for
12785               config dialogs when the main window gets focus.
12786               causing the pointer to jump back and forth.  */
12787              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
12788                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
12789                ecore_x_pointer_warp(bd->zone->container->win,
12790                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
12791              e_border_focus_set(bd, 1, 1);
12792           }
12793      }
12794 }
12795 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/