1.[E_BORDER] Change code to hide the client window in _e_border_cb_window_hide().
[platform/core/uifw/e17.git] / src / bin / e_hints.c
1 #include "e.h"
2
3 EAPI Ecore_X_Atom ATM__QTOPIA_SOFT_MENU = 0;
4 EAPI Ecore_X_Atom ATM__QTOPIA_SOFT_MENUS = 0;
5 EAPI Ecore_X_Atom ATM_GNOME_SM_PROXY = 0;
6 EAPI Ecore_X_Atom ATM_ENLIGHTENMENT_COMMS = 0;
7 EAPI Ecore_X_Atom ATM_ENLIGHTENMENT_VERSION = 0;
8 EAPI Ecore_X_Atom ATM_ENLIGHTENMENT_SCALE = 0;
9
10 EINTERN void
11 e_hints_init(void)
12 {
13    Ecore_X_Window *roots = NULL;
14    int num;
15    const char *atom_names[] = {
16       "_QTOPIA_SOFT_MENU",
17       "_QTOPIA_SOFT_MENUS",
18       "GNOME_SM_PROXY",
19       "ENLIGHTENMENT_COMMS",
20       "ENLIGHTENMENT_VERSION",
21       "ENLIGHTENMENT_SCALE"
22    };
23    Ecore_X_Atom atoms[6];
24
25    ecore_x_atoms_get(atom_names, 6, atoms);
26    ATM__QTOPIA_SOFT_MENU = atoms[0];
27    ATM__QTOPIA_SOFT_MENUS = atoms[1];
28    ATM_GNOME_SM_PROXY = atoms[2];
29    ATM_ENLIGHTENMENT_COMMS = atoms[3];
30    ATM_ENLIGHTENMENT_VERSION = atoms[4];
31    ATM_ENLIGHTENMENT_SCALE = atoms[5];
32
33    roots = ecore_x_window_root_list(&num);
34    if (roots)
35      {
36         Ecore_X_Atom supported[43];
37         int supported_num, i;
38
39         supported_num = 0;
40         /* Set what hints we support */
41         /* Root Window Properties (and Related Messages) */
42         supported[supported_num++] = ECORE_X_ATOM_NET_CLIENT_LIST;
43         supported[supported_num++] = ECORE_X_ATOM_NET_CLIENT_LIST_STACKING;
44         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS, 1);*/
45         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_DESKTOP_GEOMETRY, 1);*/
46         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_DESKTOP_VIEWPORT, 1);*/
47         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_CURRENT_DESKTOP, 1);*/
48         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_DESKTOP_NAMES, 1);*/
49         supported[supported_num++] = ECORE_X_ATOM_NET_ACTIVE_WINDOW;
50         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WORKAREA, 1);*/
51         supported[supported_num++] = ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK;
52         supported[supported_num++] = ECORE_X_ATOM_NET_VIRTUAL_ROOTS;
53         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_DESKTOP_LAYOUT, 1);*/
54         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_SHOWING_DESKTOP, 1);*/
55
56         /* Other Root Window Messages */
57         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_CLOSE_WINDOW, 1);*/
58         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_MOVERESIZE_WINDOW, 1);*/
59         supported[supported_num++] = ECORE_X_ATOM_NET_WM_MOVERESIZE;
60         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_RESTACK_WINDOW, 1);*/
61         supported[supported_num++] = ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS;
62
63         /* Application Window Properties */
64         supported[supported_num++] = ECORE_X_ATOM_NET_WM_NAME;
65         supported[supported_num++] = ECORE_X_ATOM_NET_WM_VISIBLE_NAME;
66         supported[supported_num++] = ECORE_X_ATOM_NET_WM_ICON_NAME;
67         supported[supported_num++] = ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME;
68         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_DESKTOP, 1);*/
69         supported[supported_num++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE;
70         supported[supported_num++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP;
71         supported[supported_num++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK;
72         supported[supported_num++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR;
73         supported[supported_num++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU;
74         supported[supported_num++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY;
75         supported[supported_num++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH;
76         supported[supported_num++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG;
77         supported[supported_num++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL;
78         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE;
79         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_MODAL;
80         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_STICKY;
81         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT;
82         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ;
83         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_SHADED;
84         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR;
85         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER;
86         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_HIDDEN;
87         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN;
88         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_ABOVE;
89         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STATE_BELOW;
90         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION, 1);*/
91         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, 1);*/
92         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ACTION_MOVE, 1);*/
93         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ACTION_RESIZE, 1);*/
94         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE, 1);*/
95         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ACTION_SHADE, 1);*/
96         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ACTION_STICK, 1);*/
97         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ, 1);*/
98         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT, 1);*/
99         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN, 1);*/
100         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP, 1);*/
101         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ACTION_CLOSE, 1);*/
102         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STRUT;
103         supported[supported_num++] = ECORE_X_ATOM_NET_WM_STRUT_PARTIAL;
104         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, 1);*/
105         supported[supported_num++] = ECORE_X_ATOM_NET_WM_ICON;
106         supported[supported_num++] = ECORE_X_ATOM_NET_WM_PID;
107         /*ecore_x_netwm_supported(roots[supported_num], ECORE_X_ATOM_NET_WM_HANDLED_ICONS, 1);*/
108         supported[supported_num++] = ECORE_X_ATOM_NET_WM_USER_TIME;
109         supported[supported_num++] = ECORE_X_ATOM_NET_FRAME_EXTENTS;
110         supported[supported_num++] = ECORE_X_ATOM_NET_WM_PING;
111         supported[supported_num++] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
112         supported[supported_num++] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER;
113         supported[supported_num++] = ECORE_X_ATOM_E_VIDEO_PARENT;
114         supported[supported_num++] = ECORE_X_ATOM_E_VIDEO_POSITION;
115
116         for (i = 0; i < num; i++)
117           {
118              Ecore_X_Window win, twin;
119              int nwins;
120              char *name;
121              double ts;
122
123              /* check for previous netwm wm and wait for it to die */
124              ts = ecore_time_get();
125              nwins = ecore_x_window_prop_window_get(roots[i],
126                                                     ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
127                                                     &win, 1);
128              if (nwins > 0)
129                {
130                   for (;; )
131                     {
132                        nwins = ecore_x_window_prop_window_get(win,
133                                                               ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
134                                                               &twin, 1);
135                        if (nwins < 1) break;
136                        if (twin != win) break;
137                        if (ecore_x_netwm_name_get(win, &name))
138                          {
139                             if (name)
140                               {
141                                  if (strcmp(name, "Enlightenment"))
142                                    {
143                                       free(name);
144                                       break;
145                                    }
146                                  free(name);
147                               }
148                          }
149                        ecore_x_sync();
150                        if ((ecore_time_get() - ts) > 2.0)
151                          {
152                             e_error_message_show(_("A previous instance of Enlightenment is still active\n"
153                                                    "on this screen. Aborting startup.\n"));
154                             exit(1);
155                          }
156                     }
157                }
158
159              /* TODO: Remember this window and close it on shutdown */
160              win = ecore_x_window_new(roots[i], -200, -200, 5, 5);
161 /*
162  * I don't FUCKING believe it. if we PRETEND we are Kwin - java is happy.
163  * why? it expects a double reparenting wm then. java insists on finding this
164  * out when it should be irrelevant! stupid code! I can't believe the time we
165  * just wasted hunting a bug that wasn't and that is due to sheer stupid
166  * coding (in java's awt layer that swing also uses).
167  */
168 /* Now for more stupidity... Openoffice.org will change its look and feel
169  * depending on what wm it thinks there is... so if we pretend to be Kwin...
170  * it tries to use kde preferences, if found.
171  */
172 /* I have disabled this now by pretending to be E16 with e16 comms. this
173  * means java plays nice and uses our FRAME property.. but we had to do other
174  * evil stuff as java EXPECTS all this at REPARENT time... i've deferred
175  * reparenting... i hate java!
176  */
177 /*           ecore_x_netwm_wm_identify(roots[i], win, "KWin");*/
178              ecore_x_netwm_wm_identify(roots[i], win, "Enlightenment");
179 /* this makes openoffice.org read gtk settings so it doesn't look like shit */
180              e_hints_openoffice_gnome_fake(roots[i]);
181
182              ecore_x_netwm_supported_set(roots[i], supported, supported_num);
183
184              /* fake mwm, this might crash some ol' motif apps, if
185                 they still exist, but at least it makes borderless
186                 feature of Eterm and urxvt work... */
187              ecore_x_atom_get("_MOTIF_WM_INFO");
188           }
189         free(roots);
190      }
191 }
192
193 /*
194  * This is here so we don't have to pretend to be Kwin anymore - we pretend
195  * to do old e16 style ipc. in fact we just ignore it... but set up the
196  * window port anyway
197  */
198 EAPI void
199 e_hints_e16_comms_pretend(E_Manager *man)
200 {
201    Ecore_X_Window win;
202    char buf[256];
203
204    win = ecore_x_window_input_new(man->root, -100, -100, 1, 1);
205
206    /* to help detect this is NOT e16 */
207    snprintf(buf, sizeof(buf), "Enlightenment %s", VERSION);
208    ecore_x_window_prop_property_set(win, ATM_ENLIGHTENMENT_VERSION, ECORE_X_ATOM_STRING, 8, buf, strlen(buf));
209    ecore_x_window_prop_property_set(man->root, ATM_ENLIGHTENMENT_VERSION, ECORE_X_ATOM_STRING, 8, buf, strlen(buf));
210
211    snprintf(buf, sizeof(buf), "WINID %8x", (int)win);
212    ecore_x_window_prop_property_set(win, ATM_ENLIGHTENMENT_COMMS, ECORE_X_ATOM_STRING, 8, buf, 14);
213
214    ecore_x_window_prop_property_set(man->root, ATM_ENLIGHTENMENT_COMMS, ECORE_X_ATOM_STRING, 8, buf, 14);
215 }
216
217 EINTERN void
218 e_hints_manager_init(E_Manager *man)
219 {
220    /* Set desktop count, desktop names and workarea */
221     int i = 0, num = 0;
222     unsigned int *areas = NULL;
223     Eina_List *cl;
224     E_Container *c;
225     Ecore_X_Window *vroots = NULL;
226     /* FIXME: Desktop names not yet implemented */
227 /*   char                       **names; */
228
229     e_hints_e16_comms_pretend(man);
230
231     num = eina_list_count(man->containers);
232
233     vroots = calloc(num, sizeof(Ecore_X_Window));
234     if (!vroots) return;
235
236 /*   names = calloc(num, sizeof(char *));*/
237
238     areas = calloc(4 * num, sizeof(unsigned int));
239     if (!areas)
240       {
241          free(vroots);
242          return;
243       }
244
245     EINA_LIST_FOREACH(man->containers, cl, c)
246       {
247          areas[4 * i] = c->x;
248          areas[4 * i + 1] = c->y;
249          areas[4 * i + 2] = c->w;
250          areas[4 * i + 3] = c->h;
251          vroots[i++] = c->win;
252       }
253
254 #if 0
255     ecore_x_netwm_desk_count_set(man->root, num);
256     /* No need for workarea without desktops */
257     ecore_x_netwm_desk_workareas_set(man->root, num, areas);
258 #endif
259
260     free(vroots);
261     free(areas);
262 }
263
264 /* FIXME, this should set the list in map order, not stack order */
265 EAPI void
266 e_hints_client_list_set(void)
267 {
268    Eina_List *ml = NULL, *cl = NULL;
269    unsigned int i = 0, num = 0;
270    E_Manager *m;
271    E_Container *c;
272    E_Border_List *bl;
273    E_Border *b;
274    Ecore_X_Window *clients = NULL;
275
276    /* Get client count by adding client lists on all containers */
277    EINA_LIST_FOREACH(e_manager_list(), ml, m)
278      {
279         EINA_LIST_FOREACH(m->containers, cl, c)
280           {
281              num += e_container_borders_count(c);
282           }
283      }
284
285    clients = calloc(num, sizeof(Ecore_X_Window));
286    if (!clients)
287      return;
288
289    /* Fetch window IDs and add to array */
290    if (num > 0)
291      {
292         EINA_LIST_FOREACH(e_manager_list(), ml, m)
293           {
294              i = 0;
295              EINA_LIST_FOREACH(m->containers, cl, c)
296                {
297                   bl = e_container_border_list_first(c);
298                   while ((b = e_container_border_list_next(bl)))
299                     clients[i++] = b->client.win;
300                   e_container_border_list_free(bl);
301                }
302              if (i > 0)
303                {
304                   ecore_x_netwm_client_list_stacking_set(m->root, clients, i);
305                   ecore_x_netwm_client_list_set(m->root, clients, i);
306                }
307              else
308                {
309                   ecore_x_netwm_client_list_set(m->root, NULL, 0);
310                   ecore_x_netwm_client_list_stacking_set(m->root, NULL, 0);
311                }
312           }
313      }
314    else
315      {
316         EINA_LIST_FOREACH(e_manager_list(), ml, m)
317           {
318              ecore_x_netwm_client_list_set(m->root, NULL, 0);
319              ecore_x_netwm_client_list_stacking_set(m->root, NULL, 0);
320           }
321      }
322    E_FREE(clients);
323 }
324
325 /* Client list is already in stacking order, so this function is nearly
326  * identical to the previous one */
327 EAPI void
328 e_hints_client_stacking_set(void)
329 {
330    Eina_List *ml = NULL, *cl = NULL;
331    unsigned int i = 0, num = 0;
332    E_Manager *m;
333    E_Container *c;
334    E_Border_List *bl;
335    E_Border *b;
336    Ecore_X_Window *clients = NULL;
337
338    /* Get client count */
339    EINA_LIST_FOREACH(e_manager_list(), ml, m)
340      {
341         EINA_LIST_FOREACH(m->containers, cl, c)
342           {
343              num += e_container_borders_count(c);
344           }
345      }
346
347    if (num > 0)
348      {
349         clients = calloc(num, sizeof(Ecore_X_Window));
350         if (!clients) return;
351
352         EINA_LIST_FOREACH(e_manager_list(), ml, m)
353           {
354              EINA_LIST_FOREACH(m->containers, cl, c)
355                {
356                   bl = e_container_border_list_first(c);
357                   while ((b = e_container_border_list_next(bl)))
358                     {
359                        if (i >= num)
360                          {
361                             e_error_message_show("e_hints.c: e_hints_client_stacking_set()\n"
362                                                  "\n"
363                                                  "Window list size greater than window count.\n"
364                                                  "This is really bad.\n"
365                                                  "Please report this.\n");
366                             break;
367                          }
368                        clients[i++] = b->client.win;
369                     }
370                   e_container_border_list_free(bl);
371                }
372           }
373         if (i < num)
374           {
375              e_error_message_show("e_hints.c: e_hints_client_stacking_set()\n"
376                                   "\n"
377                                   "Window list size less than window count.\n"
378                                   "This is strange, but not harmful.\n"
379                                   "Please report this.\n");
380           }
381         EINA_LIST_FOREACH(e_manager_list(), ml, m)
382           {
383              ecore_x_netwm_client_list_stacking_set(m->root, clients, num);
384           }
385         E_FREE(clients);
386      }
387    else
388      {
389         EINA_LIST_FOREACH(e_manager_list(), ml, m)
390           {
391              ecore_x_netwm_client_list_stacking_set(m->root, NULL, 0);
392           }
393      }
394 }
395
396 EAPI void
397 e_hints_active_window_set(E_Manager *man,
398                           E_Border  *bd)
399 {
400    E_OBJECT_CHECK(man);
401    if (bd)
402      ecore_x_netwm_client_active_set(man->root, bd->client.win);
403    else
404      ecore_x_netwm_client_active_set(man->root, 0);
405 }
406
407 EINTERN void
408 e_hints_window_init(E_Border *bd)
409 {
410    E_Remember *rem = NULL;
411
412    if (bd->remember)
413      rem = bd->remember;
414
415    if (bd->client.icccm.state == ECORE_X_WINDOW_STATE_HINT_NONE)
416      {
417         if (bd->client.netwm.state.hidden)
418           bd->client.icccm.state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
419         else
420           bd->client.icccm.state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
421      }
422
423 #ifdef _F_TRANSIENT_FOR_PATCH_
424    if ((!bd->parent) ||
425        (!e_config->transient.layer))
426      {
427         if ((rem) && (rem->prop.layer))
428           {
429              bd->layer = rem->prop.layer;
430              e_border_layer_set(bd, bd->layer);
431           }
432         else
433           {
434              if (!bd->lock_client_stacking)
435                {
436                   if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DESKTOP)
437                     e_border_layer_set(bd, 0);
438                   else if (bd->client.netwm.state.stacking == E_STACKING_BELOW)
439                     e_border_layer_set(bd, 50);
440                   else if (bd->client.netwm.state.stacking == E_STACKING_ABOVE)
441                     e_border_layer_set(bd, 150);
442                   else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
443                     e_border_layer_set(bd, 150);
444 #ifdef _F_NOTIFICATION_LAYER_POLICY_
445                   else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_NOTIFICATION)
446                     e_border_layer_set(bd, 300);
447 #endif
448                   else
449                     e_border_layer_set(bd, 100);
450                }
451              else
452                e_border_raise(bd);
453           }
454      }
455 #else
456    if ((rem) && (rem->prop.layer))
457      {
458         bd->layer = rem->prop.layer;
459         e_border_layer_set(bd, bd->layer);
460      }
461    else
462      {
463         if (!bd->lock_client_stacking)
464           {
465              if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DESKTOP)
466                e_border_layer_set(bd, 0);
467              else if (bd->client.netwm.state.stacking == E_STACKING_BELOW)
468                e_border_layer_set(bd, 50);
469              else if (bd->client.netwm.state.stacking == E_STACKING_ABOVE)
470                e_border_layer_set(bd, 150);
471              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
472                e_border_layer_set(bd, 150);
473 #ifdef _F_NOTIFICATION_LAYER_POLICY_
474              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_NOTIFICATION)
475                e_border_layer_set(bd, 300);
476 #endif
477              else
478                e_border_layer_set(bd, 100);
479           }
480         else
481           e_border_raise(bd);
482      }
483
484    if ((bd->parent) && (e_config->transient.layer))
485      e_border_layer_set(bd, bd->parent->layer);
486 #endif
487
488 #if 0
489    /* Ignore this, E has incompatible desktop setup */
490    if (ecore_x_netwm_desktop_get(bd->client.win, &bd->client.netwm.desktop))
491      {
492         if (bd->client.netwm.desktop == 0xffffffff)
493           {
494              e_border_stick(bd);
495           }
496         else if (bd->client.netwm.desktop < (bd->zone->desk_x_count * bd->zone->desk_y_count))
497           {
498              E_Desk *desk;
499
500              desk = e_desk_at_pos_get(bd->zone, bd->client.netwm.desktop);
501              if (desk)
502                e_border_desk_set(bd, desk);
503           }
504         else
505           {
506              /* Update netwm desktop with current desktop */
507               e_hints_window_desktop_set(bd);
508           }
509      }
510    else
511      {
512         /* Update netwm desktop with current desktop */
513          e_hints_window_desktop_set(bd);
514      }
515 #endif
516
517    if (bd->client.netwm.state.sticky)
518      {
519         if (!bd->lock_client_sticky)
520           e_border_stick(bd);
521         else
522           e_hints_window_sticky_set(bd, 0);
523      }
524    if (bd->client.netwm.state.shaded)
525      {
526         if (!bd->lock_client_shade)
527           e_border_shade(bd, e_hints_window_shade_direction_get(bd));
528         else
529           e_hints_window_shaded_set(bd, 0);
530      }
531    if ((bd->client.netwm.state.maximized_v) && (bd->client.netwm.state.maximized_h))
532      {
533         if (!bd->lock_client_maximize)
534           {
535              e_hints_window_size_get(bd);
536              e_border_maximize(bd, e_config->maximize_policy);
537           }
538         else
539           e_hints_window_maximized_set(bd, 0, 0);
540      }
541    else if (bd->client.netwm.state.maximized_h)
542      {
543         if (!bd->lock_client_maximize)
544           {
545              e_hints_window_size_get(bd);
546              e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_HORIZONTAL);
547           }
548         else
549           e_hints_window_maximized_set(bd, 0, 0);
550      }
551    else if (bd->client.netwm.state.maximized_v)
552      {
553         if (!bd->lock_client_maximize)
554           {
555              e_hints_window_size_get(bd);
556              e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_VERTICAL);
557           }
558         else
559           e_hints_window_maximized_set(bd, 0, 0);
560      }
561    if (bd->client.netwm.state.fullscreen)
562      {
563         if (!bd->lock_client_fullscreen)
564           {
565              e_hints_window_size_get(bd);
566              e_border_fullscreen(bd, e_config->fullscreen_policy);
567           }
568         else
569           e_hints_window_fullscreen_set(bd, 0);
570      }
571    if ((bd->client.icccm.state == ECORE_X_WINDOW_STATE_HINT_ICONIC) &&
572        (bd->client.netwm.state.hidden))
573      {
574         if (!bd->lock_client_iconify)
575           e_border_iconify(bd);
576         else
577           e_hints_window_visible_set(bd);
578      }
579 #ifndef _F_USE_EXTENDED_ICONIFY_
580    else if ((bd->parent) && (e_config->transient.iconify) && (bd->parent->iconic))
581      e_border_iconify(bd);
582 #endif
583    /* If a window isn't iconic, and is one the current desk,
584     * show it! */
585    else if (bd->desk == e_desk_current_get(bd->zone))
586      e_border_show(bd);
587    /* e hints */
588 /*
589    if (bd->client.e.state.centered)
590      {
591         e_border_center(bd);
592      }
593  */
594 /* Update stacking */
595    e_hints_client_list_set();
596    e_hints_client_stacking_set();
597 }
598
599 EAPI void
600 e_hints_window_state_set(E_Border *bd)
601 {
602    Ecore_X_Window_State state[10];
603    int num = 0;
604
605    if (bd->client.netwm.state.modal)
606      state[num++] = ECORE_X_WINDOW_STATE_MODAL;
607    if (bd->client.netwm.state.sticky)
608      state[num++] = ECORE_X_WINDOW_STATE_STICKY;
609    if (bd->client.netwm.state.maximized_v)
610      state[num++] = ECORE_X_WINDOW_STATE_MAXIMIZED_VERT;
611    if (bd->client.netwm.state.maximized_h)
612      state[num++] = ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ;
613    if (bd->client.netwm.state.shaded)
614      state[num++] = ECORE_X_WINDOW_STATE_SHADED;
615    if (bd->client.netwm.state.skip_taskbar)
616      state[num++] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
617    if (bd->client.netwm.state.skip_pager)
618      state[num++] = ECORE_X_WINDOW_STATE_SKIP_PAGER;
619    if (bd->client.netwm.state.hidden)
620      state[num++] = ECORE_X_WINDOW_STATE_HIDDEN;
621    if (bd->client.netwm.state.fullscreen)
622      state[num++] = ECORE_X_WINDOW_STATE_FULLSCREEN;
623
624    switch (bd->client.netwm.state.stacking)
625      {
626       case E_STACKING_ABOVE:
627         state[num++] = ECORE_X_WINDOW_STATE_ABOVE;
628         break;
629
630       case E_STACKING_BELOW:
631         state[num++] = ECORE_X_WINDOW_STATE_BELOW;
632         break;
633
634       case E_STACKING_NONE:
635       default:
636         break;
637      }
638    ecore_x_netwm_window_state_set(bd->client.win, state, num);
639 }
640
641 EAPI void
642 e_hints_allowed_action_set(E_Border *bd)
643 {
644    Ecore_X_Action action[10];
645    int num = 0;
646
647    if (bd->client.netwm.action.move)
648      action[num++] = ECORE_X_ACTION_MOVE;
649    if (bd->client.netwm.action.resize)
650      action[num++] = ECORE_X_ACTION_RESIZE;
651    if (bd->client.netwm.action.minimize)
652      action[num++] = ECORE_X_ACTION_MINIMIZE;
653    if (bd->client.netwm.action.shade)
654      action[num++] = ECORE_X_ACTION_SHADE;
655    if (bd->client.netwm.action.stick)
656      action[num++] = ECORE_X_ACTION_STICK;
657    if (bd->client.netwm.action.maximized_h)
658      action[num++] = ECORE_X_ACTION_MAXIMIZE_HORZ;
659    if (bd->client.netwm.action.maximized_v)
660      action[num++] = ECORE_X_ACTION_MAXIMIZE_VERT;
661    if (bd->client.netwm.action.fullscreen)
662      action[num++] = ECORE_X_ACTION_FULLSCREEN;
663    if (bd->client.netwm.action.change_desktop)
664      action[num++] = ECORE_X_ACTION_CHANGE_DESKTOP;
665    if (bd->client.netwm.action.close)
666      action[num++] = ECORE_X_ACTION_CLOSE;
667
668    ecore_x_netwm_allowed_action_set(bd->client.win, action, num);
669 }
670
671 EAPI void
672 e_hints_window_type_set(E_Border *bd)
673 {
674    ecore_x_netwm_window_type_set(bd->client.win, bd->client.netwm.type);
675 }
676
677 EAPI void
678 e_hints_window_type_get(E_Border *bd)
679 {
680    Ecore_X_Window_Type *types = NULL;
681    int num, i, j;
682
683    num = ecore_x_netwm_window_types_get(bd->client.win, &types);
684    if (bd->client.netwm.extra_types)
685      {
686         free(bd->client.netwm.extra_types);
687         bd->client.netwm.extra_types = NULL;
688         bd->client.netwm.extra_types_num = 0;
689      }
690    if (num == 0)
691      bd->client.netwm.type = ECORE_X_WINDOW_TYPE_UNKNOWN;
692    else
693      {
694         j = 0;
695         bd->client.netwm.type = types[j];
696         j++;
697         while ((j < num) &&
698                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN))
699           {
700              j++;
701              bd->client.netwm.type = types[j];
702           }
703         if (num > j)
704           {
705              bd->client.netwm.extra_types =
706                malloc((num - j) * sizeof(Ecore_X_Window_Type));
707              if (bd->client.netwm.extra_types)
708                {
709                   for (i = j + 1; i < num; i++)
710                     bd->client.netwm.extra_types[i - (j + 1)] = types[i];
711                   bd->client.netwm.extra_types_num = num - j;
712                }
713           }
714         free(types);
715      }
716 }
717
718 EAPI void
719 e_hints_window_state_update(E_Border                   *bd,
720                             Ecore_X_Window_State        state,
721                             Ecore_X_Window_State_Action action)
722 {
723    switch (state)
724      {
725       case ECORE_X_WINDOW_STATE_ICONIFIED:
726         if (action != ECORE_X_WINDOW_STATE_ACTION_ADD) return;
727         if (bd->client.icccm.state == ECORE_X_WINDOW_STATE_HINT_ICONIC) return;
728         if (bd->lock_client_iconify) return;
729         e_border_iconify(bd);
730         break;
731
732       case ECORE_X_WINDOW_STATE_MODAL:
733         switch (action)
734           {
735            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
736              if (bd->client.netwm.state.modal)
737                {
738                   bd->client.netwm.state.modal = 0;
739                   bd->client.netwm.update.state = 1;
740                   bd->changed = 1;
741                }
742              break;
743
744            case ECORE_X_WINDOW_STATE_ACTION_ADD:
745              if (!bd->client.netwm.state.modal)
746                {
747                   bd->client.netwm.state.modal = 1;
748                   bd->client.netwm.update.state = 1;
749                   bd->changed = 1;
750                }
751              break;
752
753            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
754              bd->client.netwm.state.modal = !bd->client.netwm.state.modal;
755              bd->client.netwm.update.state = 1;
756              bd->changed = 1;
757              break;
758           }
759         break;
760
761       case ECORE_X_WINDOW_STATE_STICKY:
762         if (bd->lock_client_sticky) return;
763         switch (action)
764           {
765            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
766              e_border_unstick(bd);
767              break;
768
769            case ECORE_X_WINDOW_STATE_ACTION_ADD:
770              e_border_stick(bd);
771              break;
772
773            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
774              if (bd->sticky)
775                e_border_unstick(bd);
776              else
777                e_border_stick(bd);
778              break;
779           }
780         break;
781
782       case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
783         if (bd->lock_client_maximize) return;
784         switch (action)
785           {
786            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
787              if (bd->maximized & E_MAXIMIZE_VERTICAL)
788                e_border_unmaximize(bd, E_MAXIMIZE_VERTICAL);
789              break;
790
791            case ECORE_X_WINDOW_STATE_ACTION_ADD:
792              if (!(bd->maximized & E_MAXIMIZE_VERTICAL))
793                e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_VERTICAL);
794              break;
795
796            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
797              if (bd->maximized & E_MAXIMIZE_VERTICAL)
798                e_border_unmaximize(bd, E_MAXIMIZE_VERTICAL);
799              else
800                e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_VERTICAL);
801              break;
802           }
803         break;
804
805       case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
806         if (bd->lock_client_maximize) return;
807         switch (action)
808           {
809            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
810              if (bd->maximized & E_MAXIMIZE_HORIZONTAL)
811                e_border_unmaximize(bd, E_MAXIMIZE_HORIZONTAL);
812              break;
813
814            case ECORE_X_WINDOW_STATE_ACTION_ADD:
815              if (!(bd->maximized & E_MAXIMIZE_HORIZONTAL))
816                e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_HORIZONTAL);
817              break;
818
819            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
820              if (bd->maximized & E_MAXIMIZE_HORIZONTAL)
821                e_border_unmaximize(bd, E_MAXIMIZE_HORIZONTAL);
822              else
823                e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_HORIZONTAL);
824              break;
825           }
826         break;
827
828       case ECORE_X_WINDOW_STATE_SHADED:
829         if (bd->lock_client_shade) return;
830         switch (action)
831           {
832            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
833              e_border_unshade(bd, e_hints_window_shade_direction_get(bd));
834              break;
835
836            case ECORE_X_WINDOW_STATE_ACTION_ADD:
837              e_border_shade(bd, e_hints_window_shade_direction_get(bd));
838              break;
839
840            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
841              if (bd->shaded)
842                e_border_unshade(bd, e_hints_window_shade_direction_get(bd));
843              else
844                e_border_shade(bd, e_hints_window_shade_direction_get(bd));
845              break;
846           }
847         break;
848
849       case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
850         switch (action)
851           {
852            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
853              if (bd->client.netwm.state.skip_taskbar)
854                {
855                   bd->client.netwm.state.skip_taskbar = 0;
856                   bd->client.netwm.update.state = 1;
857                   bd->changed = 1;
858                }
859              break;
860
861            case ECORE_X_WINDOW_STATE_ACTION_ADD:
862              if (!bd->client.netwm.state.skip_taskbar)
863                {
864                   bd->client.netwm.state.skip_taskbar = 1;
865                   bd->client.netwm.update.state = 1;
866                   bd->changed = 1;
867                }
868              break;
869
870            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
871              bd->client.netwm.state.skip_taskbar = !bd->client.netwm.state.skip_taskbar;
872              bd->client.netwm.update.state = 1;
873              bd->changed = 1;
874              break;
875           }
876         break;
877
878       case ECORE_X_WINDOW_STATE_SKIP_PAGER:
879         switch (action)
880           {
881            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
882              if (bd->client.netwm.state.skip_pager)
883                {
884                   bd->client.netwm.state.skip_pager = 0;
885                   bd->client.netwm.update.state = 1;
886                   bd->changed = 1;
887                }
888              break;
889
890            case ECORE_X_WINDOW_STATE_ACTION_ADD:
891              if (!bd->client.netwm.state.skip_pager)
892                {
893                   bd->client.netwm.state.skip_pager = 1;
894                   bd->client.netwm.update.state = 1;
895                   bd->changed = 1;
896                }
897              break;
898
899            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
900              bd->client.netwm.state.skip_pager = !bd->client.netwm.state.skip_pager;
901              bd->client.netwm.update.state = 1;
902              bd->changed = 1;
903              break;
904           }
905         break;
906
907       case ECORE_X_WINDOW_STATE_HIDDEN:
908         /* XXX: fixme */
909         break;
910
911       case ECORE_X_WINDOW_STATE_FULLSCREEN:
912         if (bd->lock_client_fullscreen) return;
913         switch (action)
914           {
915            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
916              e_border_unfullscreen(bd);
917              break;
918
919            case ECORE_X_WINDOW_STATE_ACTION_ADD:
920              e_border_fullscreen(bd, e_config->fullscreen_policy);
921              break;
922
923            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
924              if (bd->fullscreen)
925                e_border_unfullscreen(bd);
926              else
927                e_border_fullscreen(bd, e_config->fullscreen_policy);
928              break;
929           }
930         break;
931
932       case ECORE_X_WINDOW_STATE_ABOVE:
933         if (bd->lock_client_stacking) return;
934         /* FIXME: Should this require that BELOW is set to 0 first, or just
935          * do it? */
936         switch (action)
937           {
938            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
939              e_border_layer_set(bd, 100);
940              e_hints_window_stacking_set(bd, E_STACKING_NONE);
941              break;
942
943            case ECORE_X_WINDOW_STATE_ACTION_ADD:
944              e_hints_window_stacking_set(bd, E_STACKING_ABOVE);
945              e_border_layer_set(bd, 150);
946              break;
947
948            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
949              if (bd->layer == 150)
950                {
951                   e_hints_window_stacking_set(bd, E_STACKING_NONE);
952                   e_border_layer_set(bd, 100);
953                }
954              else
955                {
956                   e_hints_window_stacking_set(bd, E_STACKING_ABOVE);
957                   e_border_layer_set(bd, 150);
958                }
959              break;
960           }
961         break;
962
963       case ECORE_X_WINDOW_STATE_BELOW:
964         if (bd->lock_client_stacking) return;
965         /* FIXME: Should this require that ABOVE is set to 0 first, or just
966          * do it? */
967         switch (action)
968           {
969            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
970              e_hints_window_stacking_set(bd, E_STACKING_NONE);
971              e_border_layer_set(bd, 100);
972              break;
973
974            case ECORE_X_WINDOW_STATE_ACTION_ADD:
975              e_hints_window_stacking_set(bd, E_STACKING_BELOW);
976              e_border_layer_set(bd, 50);
977              break;
978
979            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
980              if (bd->layer == 50)
981                {
982                   e_hints_window_stacking_set(bd, E_STACKING_NONE);
983                   e_border_layer_set(bd, 100);
984                }
985              else
986                {
987                   e_hints_window_stacking_set(bd, E_STACKING_BELOW);
988                   e_border_layer_set(bd, 50);
989                }
990              break;
991           }
992         break;
993
994       case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
995         /* FIXME */
996         break;
997
998       case ECORE_X_WINDOW_STATE_UNKNOWN:
999         /* Ignore */
1000         break;
1001      }
1002 }
1003
1004 EAPI void
1005 e_hints_window_state_get(E_Border *bd)
1006 {
1007    unsigned int i, num;
1008    Ecore_X_Window_State *state;
1009
1010    bd->client.netwm.state.modal = 0;
1011    bd->client.netwm.state.sticky = 0;
1012    bd->client.netwm.state.maximized_v = 0;
1013    bd->client.netwm.state.maximized_h = 0;
1014    bd->client.netwm.state.shaded = 0;
1015    bd->client.netwm.state.skip_taskbar = 0;
1016    bd->client.netwm.state.skip_pager = 0;
1017    bd->client.netwm.state.hidden = 0;
1018    bd->client.netwm.state.fullscreen = 0;
1019    bd->client.netwm.state.stacking = 0;
1020
1021    ecore_x_netwm_window_state_get(bd->client.win, &state, &num);
1022    if (state)
1023      {
1024         for (i = 0; i < num; i++)
1025           {
1026              switch (state[i])
1027                {
1028                 case ECORE_X_WINDOW_STATE_ICONIFIED:
1029                   /* Ignore */
1030                   break;
1031
1032                 case ECORE_X_WINDOW_STATE_MODAL:
1033                   bd->client.netwm.state.modal = 1;
1034                   break;
1035
1036                 case ECORE_X_WINDOW_STATE_STICKY:
1037                   bd->client.netwm.state.sticky = 1;
1038                   break;
1039
1040                 case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
1041                   bd->client.netwm.state.maximized_v = 1;
1042                   break;
1043
1044                 case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
1045                   bd->client.netwm.state.maximized_h = 1;
1046                   break;
1047
1048                 case ECORE_X_WINDOW_STATE_SHADED:
1049                   bd->client.netwm.state.shaded = 1;
1050                   break;
1051
1052                 case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
1053                   bd->client.netwm.state.skip_taskbar = 1;
1054                   break;
1055
1056                 case ECORE_X_WINDOW_STATE_SKIP_PAGER:
1057                   bd->client.netwm.state.skip_pager = 1;
1058                   break;
1059
1060                 case ECORE_X_WINDOW_STATE_HIDDEN:
1061                   bd->client.netwm.state.hidden = 1;
1062                   break;
1063
1064                 case ECORE_X_WINDOW_STATE_FULLSCREEN:
1065                   bd->client.netwm.state.fullscreen = 1;
1066                   break;
1067
1068                 case ECORE_X_WINDOW_STATE_ABOVE:
1069                   bd->client.netwm.state.stacking = E_STACKING_ABOVE;
1070                   break;
1071
1072                 case ECORE_X_WINDOW_STATE_BELOW:
1073                   bd->client.netwm.state.stacking = E_STACKING_BELOW;
1074                   break;
1075
1076                 case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
1077                   /* FIXME */
1078                   break;
1079
1080                 case ECORE_X_WINDOW_STATE_UNKNOWN:
1081                   /* Ignore */
1082                   break;
1083                }
1084           }
1085         free(state);
1086      }
1087 }
1088
1089 EAPI void
1090 e_hints_allowed_action_update(E_Border *bd   __UNUSED__,
1091                               Ecore_X_Action action)
1092 {
1093    switch (action)
1094      {
1095       case ECORE_X_ACTION_MOVE:
1096         break;
1097
1098       case ECORE_X_ACTION_RESIZE:
1099         break;
1100
1101       case ECORE_X_ACTION_MINIMIZE:
1102         break;
1103
1104       case ECORE_X_ACTION_SHADE:
1105         break;
1106
1107       case ECORE_X_ACTION_STICK:
1108         break;
1109
1110       case ECORE_X_ACTION_MAXIMIZE_HORZ:
1111         break;
1112
1113       case ECORE_X_ACTION_MAXIMIZE_VERT:
1114         break;
1115
1116       case ECORE_X_ACTION_FULLSCREEN:
1117         break;
1118
1119       case ECORE_X_ACTION_CHANGE_DESKTOP:
1120         break;
1121
1122       case ECORE_X_ACTION_CLOSE:
1123         break;
1124
1125       case ECORE_X_ACTION_ABOVE:
1126         break;
1127
1128       case ECORE_X_ACTION_BELOW:
1129         break;
1130      }
1131 }
1132
1133 EAPI void
1134 e_hints_allowed_action_get(E_Border *bd)
1135 {
1136    Ecore_X_Action *action;
1137    unsigned int i;
1138    unsigned int num;
1139
1140    bd->client.netwm.action.move = 0;
1141    bd->client.netwm.action.resize = 0;
1142    bd->client.netwm.action.minimize = 0;
1143    bd->client.netwm.action.shade = 0;
1144    bd->client.netwm.action.stick = 0;
1145    bd->client.netwm.action.maximized_h = 0;
1146    bd->client.netwm.action.maximized_v = 0;
1147    bd->client.netwm.action.fullscreen = 0;
1148    bd->client.netwm.action.change_desktop = 0;
1149    bd->client.netwm.action.close = 0;
1150
1151    ecore_x_netwm_allowed_action_get(bd->client.win, &action, &num);
1152    if (action)
1153      {
1154         for (i = 0; i < num; i++)
1155           {
1156              switch (action[i])
1157                {
1158                 case ECORE_X_ACTION_MOVE:
1159                   bd->client.netwm.action.move = 1;
1160                   break;
1161
1162                 case ECORE_X_ACTION_RESIZE:
1163                   bd->client.netwm.action.resize = 1;
1164                   break;
1165
1166                 case ECORE_X_ACTION_MINIMIZE:
1167                   bd->client.netwm.action.minimize = 1;
1168                   break;
1169
1170                 case ECORE_X_ACTION_SHADE:
1171                   bd->client.netwm.action.shade = 1;
1172                   break;
1173
1174                 case ECORE_X_ACTION_STICK:
1175                   bd->client.netwm.action.stick = 1;
1176                   break;
1177
1178                 case ECORE_X_ACTION_MAXIMIZE_HORZ:
1179                   bd->client.netwm.action.maximized_h = 1;
1180                   break;
1181
1182                 case ECORE_X_ACTION_MAXIMIZE_VERT:
1183                   bd->client.netwm.action.maximized_v = 1;
1184                   break;
1185
1186                 case ECORE_X_ACTION_FULLSCREEN:
1187                   bd->client.netwm.action.fullscreen = 1;
1188                   break;
1189
1190                 case ECORE_X_ACTION_CHANGE_DESKTOP:
1191                   bd->client.netwm.action.change_desktop = 1;
1192                   break;
1193
1194                 case ECORE_X_ACTION_CLOSE:
1195                   bd->client.netwm.action.close = 1;
1196                   break;
1197
1198                 case ECORE_X_ACTION_ABOVE:
1199                   break;
1200
1201                 case ECORE_X_ACTION_BELOW:
1202                   break;
1203                }
1204           }
1205         free(action);
1206      }
1207 }
1208
1209 EAPI void
1210 e_hints_window_visible_set(E_Border *bd)
1211 {
1212    if (bd->client.icccm.state != ECORE_X_WINDOW_STATE_HINT_NORMAL)
1213      {
1214         ecore_x_icccm_state_set(bd->client.win, ECORE_X_WINDOW_STATE_HINT_NORMAL);
1215         bd->client.icccm.state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
1216      }
1217    if (bd->client.netwm.state.hidden)
1218      {
1219         bd->client.netwm.update.state = 1;
1220         bd->client.netwm.state.hidden = 0;
1221         bd->changed = 1;
1222      }
1223 }
1224
1225 EAPI void
1226 e_hints_window_iconic_set(E_Border *bd)
1227 {
1228    if (bd->client.icccm.state != ECORE_X_WINDOW_STATE_HINT_ICONIC)
1229      {
1230         ecore_x_icccm_state_set(bd->client.win, ECORE_X_WINDOW_STATE_HINT_ICONIC);
1231         bd->client.icccm.state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
1232      }
1233    if (!bd->client.netwm.state.hidden)
1234      {
1235         bd->client.netwm.update.state = 1;
1236         bd->client.netwm.state.hidden = 1;
1237         bd->changed = 1;
1238      }
1239 }
1240
1241 EAPI void
1242 e_hints_window_hidden_set(E_Border *bd)
1243 {
1244    if (bd->client.icccm.state != ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
1245      {
1246         ecore_x_icccm_state_set(bd->client.win, ECORE_X_WINDOW_STATE_HINT_WITHDRAWN);
1247         bd->client.icccm.state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
1248      }
1249    if (bd->client.netwm.state.hidden)
1250      {
1251         bd->client.netwm.update.state = 1;
1252         bd->client.netwm.state.hidden = 0;
1253         bd->changed = 1;
1254      }
1255 }
1256
1257 EAPI void
1258 e_hints_window_shaded_set(E_Border *bd,
1259                           int       on)
1260 {
1261    if ((!bd->client.netwm.state.shaded) && (on))
1262      {
1263         bd->client.netwm.update.state = 1;
1264         bd->client.netwm.state.shaded = 1;
1265         bd->changed = 1;
1266      }
1267    else if ((bd->client.netwm.state.shaded) && (!on))
1268      {
1269         bd->client.netwm.update.state = 1;
1270         bd->client.netwm.state.shaded = 0;
1271         bd->changed = 1;
1272      }
1273 }
1274
1275 EAPI void
1276 e_hints_window_shade_direction_set(E_Border   *bd,
1277                                    E_Direction dir)
1278 {
1279    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_SHADE_DIRECTION, &dir, 1);
1280 }
1281
1282 EAPI E_Direction
1283 e_hints_window_shade_direction_get(E_Border *bd)
1284 {
1285    int ret;
1286    E_Direction dir;
1287
1288    ret = ecore_x_window_prop_card32_get(bd->client.win,
1289                                         E_ATOM_SHADE_DIRECTION,
1290                                         &dir, 1);
1291    if (ret == 1)
1292      return dir;
1293
1294    return E_DIRECTION_UP;
1295 }
1296
1297 EAPI void
1298 e_hints_window_size_set(E_Border *bd)
1299 {
1300    unsigned int sizes[4];
1301
1302    sizes[0] = bd->x;
1303    sizes[1] = bd->y;
1304    sizes[2] = bd->w;
1305    sizes[3] = bd->h;
1306    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_BORDER_SIZE, sizes, 4);
1307 }
1308
1309 EAPI void
1310 e_hints_window_size_unset(E_Border *bd)
1311 {
1312    ecore_x_window_prop_property_del(bd->client.win, E_ATOM_BORDER_SIZE);
1313 }
1314
1315 EAPI int
1316 e_hints_window_size_get(E_Border *bd)
1317 {
1318    int ret;
1319    unsigned int sizes[4];
1320
1321    memset(sizes, 0, sizeof(sizes));
1322    ret = ecore_x_window_prop_card32_get(bd->client.win, E_ATOM_BORDER_SIZE,
1323                                         sizes, 4);
1324    if (ret != 4)
1325      return 0;
1326
1327    bd->x = sizes[0];
1328    bd->y = sizes[1];
1329    bd->w = sizes[2];
1330    bd->h = sizes[3];
1331
1332    return 1;
1333 }
1334
1335 EAPI void
1336 e_hints_window_maximized_set(E_Border *bd,
1337                              int       horizontal,
1338                              int       vertical)
1339 {
1340    if ((horizontal) && (!bd->client.netwm.state.maximized_h))
1341      {
1342         bd->client.netwm.update.state = 1;
1343         bd->client.netwm.state.maximized_h = 1;
1344         bd->changed = 1;
1345      }
1346    else if ((!horizontal) && (bd->client.netwm.state.maximized_h))
1347      {
1348         bd->client.netwm.update.state = 1;
1349         bd->client.netwm.state.maximized_h = 0;
1350         bd->changed = 1;
1351      }
1352    if ((vertical) && (!bd->client.netwm.state.maximized_v))
1353      {
1354         bd->client.netwm.update.state = 1;
1355         bd->client.netwm.state.maximized_v = 1;
1356         bd->changed = 1;
1357      }
1358    else if ((!vertical) && (bd->client.netwm.state.maximized_v))
1359      {
1360         bd->client.netwm.update.state = 1;
1361         bd->client.netwm.state.maximized_v = 0;
1362         bd->changed = 1;
1363      }
1364 }
1365
1366 EAPI void
1367 e_hints_window_fullscreen_set(E_Border *bd,
1368                               int       on)
1369 {
1370    if ((!bd->client.netwm.state.fullscreen) && (on))
1371      {
1372         bd->client.netwm.update.state = 1;
1373         bd->client.netwm.state.fullscreen = 1;
1374         bd->changed = 1;
1375      }
1376    else if ((bd->client.netwm.state.fullscreen) && (!on))
1377      {
1378         bd->client.netwm.update.state = 1;
1379         bd->client.netwm.state.fullscreen = 0;
1380         bd->changed = 1;
1381      }
1382 }
1383
1384 EAPI void
1385 e_hints_window_sticky_set(E_Border *bd,
1386                           int       on)
1387 {
1388    if ((!bd->client.netwm.state.sticky) && (on))
1389      {
1390         bd->client.netwm.update.state = 1;
1391         bd->client.netwm.state.sticky = 1;
1392         bd->changed = 1;
1393      }
1394    else if ((bd->client.netwm.state.sticky) && (!on))
1395      {
1396         bd->client.netwm.update.state = 1;
1397         bd->client.netwm.state.sticky = 0;
1398         bd->changed = 1;
1399      }
1400 }
1401
1402 EAPI void
1403 e_hints_window_stacking_set(E_Border  *bd,
1404                             E_Stacking stacking)
1405 {
1406    if (bd->client.netwm.state.stacking == stacking) return;
1407    bd->client.netwm.update.state = 1;
1408    bd->client.netwm.state.stacking = stacking;
1409    bd->changed = 1;
1410 }
1411
1412 EAPI void
1413 e_hints_window_desktop_set(E_Border *bd)
1414 {
1415    /* This function is only called when really changing desktop,
1416     * so just set the property and don't care about the roundtrip.
1417     */
1418      unsigned int deskpos[2];
1419
1420      /* if valgrind complains here it is complaining bd->client.netwm.desktop
1421       * is an uninitialised variable - but it isn't. it can't be. its part of
1422       * a calloc()'d struct and thus has to have been set to 0. hell even
1423       * e_border.c explicitly sets it to 0 on creation of the border object.
1424       */
1425      deskpos[0] = bd->desk->x;
1426      deskpos[1] = bd->desk->y;
1427      ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_DESK, deskpos, 2);
1428
1429 #ifdef _F_USE_DESK_WINDOW_PROFILE_
1430      if (strcmp(bd->desk->window_profile,
1431                 e_config->desktop_default_window_profile) != 0)
1432        {
1433           ecore_x_e_window_profile_set(bd->client.win,
1434                                        bd->desk->window_profile);
1435        }
1436 #endif
1437
1438 #if 0
1439      ecore_x_netwm_desktop_set(bd->client.win, current);
1440 #endif
1441      bd->client.netwm.desktop = (bd->desk->y * bd->zone->desk_x_count) + bd->desk->x;
1442 }
1443
1444 EAPI void
1445 e_hints_window_e_state_get(E_Border *bd)
1446 {
1447    /* Remember to update the count if we add more states! */
1448    Ecore_X_Atom state[1];
1449    int num = 0, i = 0;
1450    int size = 0;
1451
1452    memset(state, 0, sizeof(state));
1453
1454    /* ugly, but avoids possible future overflow if more states are added */
1455    size = (sizeof(state) / sizeof(state[0]));
1456
1457    num =
1458      ecore_x_window_prop_card32_get(bd->client.win, E_ATOM_WINDOW_STATE,
1459                                     state, size);
1460    if (!num) return;
1461
1462    for (i = 0; (i < num) && (i < size); i++)
1463      {
1464         if (state[i] == E_ATOM_WINDOW_STATE_CENTERED)
1465           bd->client.e.state.centered = 1;
1466      }
1467 }
1468
1469 EAPI void
1470 e_hints_window_e_state_set(E_Border *bd __UNUSED__)
1471 {
1472    /* TODO */
1473 }
1474
1475 EAPI void
1476 e_hints_window_qtopia_soft_menu_get(E_Border *bd)
1477 {
1478    unsigned int val;
1479
1480    if (ecore_x_window_prop_card32_get(bd->client.win, ATM__QTOPIA_SOFT_MENU, &val, 1))
1481      bd->client.qtopia.soft_menu = val;
1482    else
1483      bd->client.qtopia.soft_menu = 0;
1484 }
1485
1486 EAPI void
1487 e_hints_window_qtopia_soft_menus_get(E_Border *bd)
1488 {
1489    unsigned int val;
1490
1491    if (ecore_x_window_prop_card32_get(bd->client.win, ATM__QTOPIA_SOFT_MENUS, &val, 1))
1492      bd->client.qtopia.soft_menus = val;
1493    else
1494      bd->client.qtopia.soft_menus = 0;
1495 }
1496
1497 EAPI void
1498 e_hints_window_virtual_keyboard_state_get(E_Border *bd)
1499 {
1500    bd->client.vkbd.state = ecore_x_e_virtual_keyboard_state_get(bd->client.win);
1501 }
1502
1503 EAPI void
1504 e_hints_window_virtual_keyboard_get(E_Border *bd)
1505 {
1506    bd->client.vkbd.vkbd = ecore_x_e_virtual_keyboard_get(bd->client.win);
1507 }
1508
1509 EAPI void
1510 e_hints_openoffice_gnome_fake(Ecore_X_Window root)
1511 {
1512    const char *string = "ATM_GNOME_SM_PROXY";
1513
1514    ecore_x_window_prop_property_set(root, ATM_GNOME_SM_PROXY, ECORE_X_ATOM_STRING,
1515                                     8, (void *)string, strlen(string));
1516 }
1517
1518 EAPI void
1519 e_hints_openoffice_kde_fake(Ecore_X_Window root)
1520 {
1521    Ecore_X_Window win2;
1522
1523    win2 = ecore_x_window_new(root, -20, -20, 1, 1);
1524    ecore_x_netwm_wm_identify(root, win2, "KWin");
1525 }
1526
1527 EAPI void
1528 e_hints_scale_update(void)
1529 {
1530    Ecore_X_Window *roots = NULL;
1531    int i, num;
1532    unsigned int scale;
1533
1534    roots = ecore_x_window_root_list(&num);
1535    if (roots)
1536      {
1537         scale = e_scale * 1000;
1538         for (i = 0; i < num; i++)
1539           ecore_x_window_prop_card32_set(roots[i], ATM_ENLIGHTENMENT_SCALE, &scale, 1);
1540         free(roots);
1541      }
1542 }