Migrating source code to RSA from private.
[framework/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    if ((rem) && (rem->prop.layer))
424      {
425         bd->layer = rem->prop.layer;
426         e_border_layer_set(bd, bd->layer);
427      }
428    else
429      {
430         if (!bd->lock_client_stacking)
431           {
432              if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DESKTOP)
433                e_border_layer_set(bd, 0);
434              else if (bd->client.netwm.state.stacking == E_STACKING_BELOW)
435                e_border_layer_set(bd, 50);
436              else if (bd->client.netwm.state.stacking == E_STACKING_ABOVE)
437                e_border_layer_set(bd, 150);
438              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
439                e_border_layer_set(bd, 150);
440 #ifdef _F_NOTIFICATION_LAYER_POLICY_
441              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_NOTIFICATION)
442                e_border_layer_set(bd, 240);
443 #endif
444              else
445                e_border_layer_set(bd, 100);
446           }
447         else
448           e_border_raise(bd);
449      }
450
451    if ((bd->parent) && (e_config->transient.layer))
452      e_border_layer_set(bd, bd->parent->layer);
453
454 #if 0
455    /* Ignore this, E has incompatible desktop setup */
456    if (ecore_x_netwm_desktop_get(bd->client.win, &bd->client.netwm.desktop))
457      {
458         if (bd->client.netwm.desktop == 0xffffffff)
459           {
460              e_border_stick(bd);
461           }
462         else if (bd->client.netwm.desktop < (bd->zone->desk_x_count * bd->zone->desk_y_count))
463           {
464              E_Desk *desk;
465
466              desk = e_desk_at_pos_get(bd->zone, bd->client.netwm.desktop);
467              if (desk)
468                e_border_desk_set(bd, desk);
469           }
470         else
471           {
472              /* Update netwm desktop with current desktop */
473               e_hints_window_desktop_set(bd);
474           }
475      }
476    else
477      {
478         /* Update netwm desktop with current desktop */
479          e_hints_window_desktop_set(bd);
480      }
481 #endif
482
483    {
484       char *str = NULL;
485
486       if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
487           ((bd->client.icccm.client_leader > 0) &&
488            ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
489           )
490         {
491            if (!strncmp(str, "E_START|", 8))
492              {
493                 int id;
494
495                 id = atoi(str + 8);
496                 if (id > 0) bd->client.netwm.startup_id = id;
497              }
498            free(str);
499         }
500    }
501    /* It's ok not to have fetch flag, should only be set on startup
502     * and not changed. */
503    if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
504      {
505         if (bd->client.icccm.client_leader)
506           {
507              if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
508                bd->client.netwm.pid = -1;
509           }
510         else
511           bd->client.netwm.pid = -1;
512      }
513
514    if (bd->client.netwm.state.sticky)
515      {
516         if (!bd->lock_client_sticky)
517           e_border_stick(bd);
518         else
519           e_hints_window_sticky_set(bd, 0);
520      }
521    if (bd->client.netwm.state.shaded)
522      {
523         if (!bd->lock_client_shade)
524           e_border_shade(bd, e_hints_window_shade_direction_get(bd));
525         else
526           e_hints_window_shaded_set(bd, 0);
527      }
528    if ((bd->client.netwm.state.maximized_v) && (bd->client.netwm.state.maximized_h))
529      {
530         if (!bd->lock_client_maximize)
531           {
532              e_hints_window_size_get(bd);
533              e_border_maximize(bd, e_config->maximize_policy);
534           }
535         else
536           e_hints_window_maximized_set(bd, 0, 0);
537      }
538    else if (bd->client.netwm.state.maximized_h)
539      {
540         if (!bd->lock_client_maximize)
541           {
542              e_hints_window_size_get(bd);
543              e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_HORIZONTAL);
544           }
545         else
546           e_hints_window_maximized_set(bd, 0, 0);
547      }
548    else if (bd->client.netwm.state.maximized_v)
549      {
550         if (!bd->lock_client_maximize)
551           {
552              e_hints_window_size_get(bd);
553              e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_VERTICAL);
554           }
555         else
556           e_hints_window_maximized_set(bd, 0, 0);
557      }
558    if (bd->client.netwm.state.fullscreen)
559      {
560         if (!bd->lock_client_fullscreen)
561           {
562              e_hints_window_size_get(bd);
563              e_border_fullscreen(bd, e_config->fullscreen_policy);
564           }
565         else
566           e_hints_window_fullscreen_set(bd, 0);
567      }
568    if ((bd->client.icccm.state == ECORE_X_WINDOW_STATE_HINT_ICONIC) &&
569        (bd->client.netwm.state.hidden))
570      {
571         if (!bd->lock_client_iconify)
572           e_border_iconify(bd);
573         else
574           e_hints_window_visible_set(bd);
575      }
576    else if ((bd->parent) && (e_config->transient.iconify) && (bd->parent->iconic))
577      e_border_iconify(bd);
578    /* If a window isn't iconic, and is one the current desk,
579     * show it! */
580    else if (bd->desk == e_desk_current_get(bd->zone))
581      e_border_show(bd);
582    /* e hints */
583 /*
584    if (bd->client.e.state.centered)
585      {
586         e_border_center(bd);
587      }
588  */
589 /* Update stacking */
590    e_hints_client_list_set();
591    e_hints_client_stacking_set();
592 }
593
594 EAPI void
595 e_hints_window_state_set(E_Border *bd)
596 {
597    Ecore_X_Window_State state[10];
598    int num = 0;
599
600    if (bd->client.netwm.state.modal)
601      state[num++] = ECORE_X_WINDOW_STATE_MODAL;
602    if (bd->client.netwm.state.sticky)
603      state[num++] = ECORE_X_WINDOW_STATE_STICKY;
604    if (bd->client.netwm.state.maximized_v)
605      state[num++] = ECORE_X_WINDOW_STATE_MAXIMIZED_VERT;
606    if (bd->client.netwm.state.maximized_h)
607      state[num++] = ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ;
608    if (bd->client.netwm.state.shaded)
609      state[num++] = ECORE_X_WINDOW_STATE_SHADED;
610    if (bd->client.netwm.state.skip_taskbar)
611      state[num++] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
612    if (bd->client.netwm.state.skip_pager)
613      state[num++] = ECORE_X_WINDOW_STATE_SKIP_PAGER;
614    if (bd->client.netwm.state.hidden)
615      state[num++] = ECORE_X_WINDOW_STATE_HIDDEN;
616    if (bd->client.netwm.state.fullscreen)
617      state[num++] = ECORE_X_WINDOW_STATE_FULLSCREEN;
618
619    switch (bd->client.netwm.state.stacking)
620      {
621       case E_STACKING_ABOVE:
622         state[num++] = ECORE_X_WINDOW_STATE_ABOVE;
623         break;
624
625       case E_STACKING_BELOW:
626         state[num++] = ECORE_X_WINDOW_STATE_BELOW;
627         break;
628
629       case E_STACKING_NONE:
630       default:
631         break;
632      }
633    ecore_x_netwm_window_state_set(bd->client.win, state, num);
634 }
635
636 EAPI void
637 e_hints_allowed_action_set(E_Border *bd)
638 {
639    Ecore_X_Action action[10];
640    int num = 0;
641
642    if (bd->client.netwm.action.move)
643      action[num++] = ECORE_X_ACTION_MOVE;
644    if (bd->client.netwm.action.resize)
645      action[num++] = ECORE_X_ACTION_RESIZE;
646    if (bd->client.netwm.action.minimize)
647      action[num++] = ECORE_X_ACTION_MINIMIZE;
648    if (bd->client.netwm.action.shade)
649      action[num++] = ECORE_X_ACTION_SHADE;
650    if (bd->client.netwm.action.stick)
651      action[num++] = ECORE_X_ACTION_STICK;
652    if (bd->client.netwm.action.maximized_h)
653      action[num++] = ECORE_X_ACTION_MAXIMIZE_HORZ;
654    if (bd->client.netwm.action.maximized_v)
655      action[num++] = ECORE_X_ACTION_MAXIMIZE_VERT;
656    if (bd->client.netwm.action.fullscreen)
657      action[num++] = ECORE_X_ACTION_FULLSCREEN;
658    if (bd->client.netwm.action.change_desktop)
659      action[num++] = ECORE_X_ACTION_CHANGE_DESKTOP;
660    if (bd->client.netwm.action.close)
661      action[num++] = ECORE_X_ACTION_CLOSE;
662
663    ecore_x_netwm_allowed_action_set(bd->client.win, action, num);
664 }
665
666 EAPI void
667 e_hints_window_type_set(E_Border *bd)
668 {
669    ecore_x_netwm_window_type_set(bd->client.win, bd->client.netwm.type);
670 }
671
672 EAPI void
673 e_hints_window_type_get(E_Border *bd)
674 {
675    Ecore_X_Window_Type *types = NULL;
676    int num, i, j;
677
678    num = ecore_x_netwm_window_types_get(bd->client.win, &types);
679    if (bd->client.netwm.extra_types)
680      {
681         free(bd->client.netwm.extra_types);
682         bd->client.netwm.extra_types = NULL;
683         bd->client.netwm.extra_types_num = 0;
684      }
685    if (num == 0)
686      bd->client.netwm.type = ECORE_X_WINDOW_TYPE_UNKNOWN;
687    else
688      {
689         j = 0;
690         bd->client.netwm.type = types[j];
691         j++;
692         while ((j < num) &&
693                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN))
694           {
695              j++;
696              bd->client.netwm.type = types[j];
697           }
698         if (num > j)
699           {
700              bd->client.netwm.extra_types =
701                malloc((num - j) * sizeof(Ecore_X_Window_Type));
702              if (bd->client.netwm.extra_types)
703                {
704                   for (i = j + 1; i < num; i++)
705                     bd->client.netwm.extra_types[i - (j + 1)] = types[i];
706                   bd->client.netwm.extra_types_num = num - j;
707                }
708           }
709         free(types);
710      }
711 }
712
713 EAPI void
714 e_hints_window_state_update(E_Border                   *bd,
715                             Ecore_X_Window_State        state,
716                             Ecore_X_Window_State_Action action)
717 {
718    switch (state)
719      {
720       case ECORE_X_WINDOW_STATE_ICONIFIED:
721         if (action != ECORE_X_WINDOW_STATE_ACTION_ADD) return;
722         if (bd->client.icccm.state == ECORE_X_WINDOW_STATE_HINT_ICONIC) return;
723         if (bd->lock_client_iconify) return;
724         e_border_iconify(bd);
725         break;
726
727       case ECORE_X_WINDOW_STATE_MODAL:
728         switch (action)
729           {
730            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
731              if (bd->client.netwm.state.modal)
732                {
733                   bd->client.netwm.state.modal = 0;
734                   bd->client.netwm.update.state = 1;
735                   bd->changed = 1;
736                }
737              break;
738
739            case ECORE_X_WINDOW_STATE_ACTION_ADD:
740              if (!bd->client.netwm.state.modal)
741                {
742                   bd->client.netwm.state.modal = 1;
743                   bd->client.netwm.update.state = 1;
744                   bd->changed = 1;
745                }
746              break;
747
748            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
749              bd->client.netwm.state.modal = !bd->client.netwm.state.modal;
750              bd->client.netwm.update.state = 1;
751              bd->changed = 1;
752              break;
753           }
754         break;
755
756       case ECORE_X_WINDOW_STATE_STICKY:
757         if (bd->lock_client_sticky) return;
758         switch (action)
759           {
760            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
761              e_border_unstick(bd);
762              break;
763
764            case ECORE_X_WINDOW_STATE_ACTION_ADD:
765              e_border_stick(bd);
766              break;
767
768            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
769              if (bd->sticky)
770                e_border_unstick(bd);
771              else
772                e_border_stick(bd);
773              break;
774           }
775         break;
776
777       case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
778         if (bd->lock_client_maximize) return;
779         switch (action)
780           {
781            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
782              if (bd->maximized & E_MAXIMIZE_VERTICAL)
783                e_border_unmaximize(bd, E_MAXIMIZE_VERTICAL);
784              break;
785
786            case ECORE_X_WINDOW_STATE_ACTION_ADD:
787              if (!(bd->maximized & E_MAXIMIZE_VERTICAL))
788                e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_VERTICAL);
789              break;
790
791            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
792              if (bd->maximized & E_MAXIMIZE_VERTICAL)
793                e_border_unmaximize(bd, E_MAXIMIZE_VERTICAL);
794              else
795                e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_VERTICAL);
796              break;
797           }
798         break;
799
800       case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
801         if (bd->lock_client_maximize) return;
802         switch (action)
803           {
804            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
805              if (bd->maximized & E_MAXIMIZE_HORIZONTAL)
806                e_border_unmaximize(bd, E_MAXIMIZE_HORIZONTAL);
807              break;
808
809            case ECORE_X_WINDOW_STATE_ACTION_ADD:
810              if (!(bd->maximized & E_MAXIMIZE_HORIZONTAL))
811                e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_HORIZONTAL);
812              break;
813
814            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
815              if (bd->maximized & E_MAXIMIZE_HORIZONTAL)
816                e_border_unmaximize(bd, E_MAXIMIZE_HORIZONTAL);
817              else
818                e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_HORIZONTAL);
819              break;
820           }
821         break;
822
823       case ECORE_X_WINDOW_STATE_SHADED:
824         if (bd->lock_client_shade) return;
825         switch (action)
826           {
827            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
828              e_border_unshade(bd, e_hints_window_shade_direction_get(bd));
829              break;
830
831            case ECORE_X_WINDOW_STATE_ACTION_ADD:
832              e_border_shade(bd, e_hints_window_shade_direction_get(bd));
833              break;
834
835            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
836              if (bd->shaded)
837                e_border_unshade(bd, e_hints_window_shade_direction_get(bd));
838              else
839                e_border_shade(bd, e_hints_window_shade_direction_get(bd));
840              break;
841           }
842         break;
843
844       case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
845         switch (action)
846           {
847            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
848              if (bd->client.netwm.state.skip_taskbar)
849                {
850                   bd->client.netwm.state.skip_taskbar = 0;
851                   bd->client.netwm.update.state = 1;
852                   bd->changed = 1;
853                }
854              break;
855
856            case ECORE_X_WINDOW_STATE_ACTION_ADD:
857              if (!bd->client.netwm.state.skip_taskbar)
858                {
859                   bd->client.netwm.state.skip_taskbar = 1;
860                   bd->client.netwm.update.state = 1;
861                   bd->changed = 1;
862                }
863              break;
864
865            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
866              bd->client.netwm.state.skip_taskbar = !bd->client.netwm.state.skip_taskbar;
867              bd->client.netwm.update.state = 1;
868              bd->changed = 1;
869              break;
870           }
871         break;
872
873       case ECORE_X_WINDOW_STATE_SKIP_PAGER:
874         switch (action)
875           {
876            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
877              if (bd->client.netwm.state.skip_pager)
878                {
879                   bd->client.netwm.state.skip_pager = 0;
880                   bd->client.netwm.update.state = 1;
881                   bd->changed = 1;
882                }
883              break;
884
885            case ECORE_X_WINDOW_STATE_ACTION_ADD:
886              if (!bd->client.netwm.state.skip_pager)
887                {
888                   bd->client.netwm.state.skip_pager = 1;
889                   bd->client.netwm.update.state = 1;
890                   bd->changed = 1;
891                }
892              break;
893
894            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
895              bd->client.netwm.state.skip_pager = !bd->client.netwm.state.skip_pager;
896              bd->client.netwm.update.state = 1;
897              bd->changed = 1;
898              break;
899           }
900         break;
901
902       case ECORE_X_WINDOW_STATE_HIDDEN:
903         /* Ignore */
904         break;
905
906       case ECORE_X_WINDOW_STATE_FULLSCREEN:
907         if (bd->lock_client_fullscreen) return;
908         switch (action)
909           {
910            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
911              e_border_unfullscreen(bd);
912              break;
913
914            case ECORE_X_WINDOW_STATE_ACTION_ADD:
915              e_border_fullscreen(bd, e_config->fullscreen_policy);
916              break;
917
918            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
919              if (bd->fullscreen)
920                e_border_unfullscreen(bd);
921              else
922                e_border_fullscreen(bd, e_config->fullscreen_policy);
923              break;
924           }
925         break;
926
927       case ECORE_X_WINDOW_STATE_ABOVE:
928         if (bd->lock_client_stacking) return;
929         /* FIXME: Should this require that BELOW is set to 0 first, or just
930          * do it? */
931         switch (action)
932           {
933            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
934              e_border_layer_set(bd, 100);
935              e_hints_window_stacking_set(bd, E_STACKING_NONE);
936              break;
937
938            case ECORE_X_WINDOW_STATE_ACTION_ADD:
939              e_hints_window_stacking_set(bd, E_STACKING_ABOVE);
940              e_border_layer_set(bd, 150);
941              break;
942
943            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
944              if (bd->layer == 150)
945                {
946                   e_hints_window_stacking_set(bd, E_STACKING_NONE);
947                   e_border_layer_set(bd, 100);
948                }
949              else
950                {
951                   e_hints_window_stacking_set(bd, E_STACKING_ABOVE);
952                   e_border_layer_set(bd, 150);
953                }
954              break;
955           }
956         break;
957
958       case ECORE_X_WINDOW_STATE_BELOW:
959         if (bd->lock_client_stacking) return;
960         /* FIXME: Should this require that ABOVE is set to 0 first, or just
961          * do it? */
962         switch (action)
963           {
964            case ECORE_X_WINDOW_STATE_ACTION_REMOVE:
965              e_hints_window_stacking_set(bd, E_STACKING_NONE);
966              e_border_layer_set(bd, 100);
967              break;
968
969            case ECORE_X_WINDOW_STATE_ACTION_ADD:
970              e_hints_window_stacking_set(bd, E_STACKING_BELOW);
971              e_border_layer_set(bd, 50);
972              break;
973
974            case ECORE_X_WINDOW_STATE_ACTION_TOGGLE:
975              if (bd->layer == 50)
976                {
977                   e_hints_window_stacking_set(bd, E_STACKING_NONE);
978                   e_border_layer_set(bd, 100);
979                }
980              else
981                {
982                   e_hints_window_stacking_set(bd, E_STACKING_BELOW);
983                   e_border_layer_set(bd, 50);
984                }
985              break;
986           }
987         break;
988
989       case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
990         /* FIXME */
991         break;
992
993       case ECORE_X_WINDOW_STATE_UNKNOWN:
994         /* Ignore */
995         break;
996      }
997 }
998
999 EAPI void
1000 e_hints_window_state_get(E_Border *bd)
1001 {
1002    unsigned int i, num;
1003    Ecore_X_Window_State *state;
1004
1005    bd->client.netwm.state.modal = 0;
1006    bd->client.netwm.state.sticky = 0;
1007    bd->client.netwm.state.maximized_v = 0;
1008    bd->client.netwm.state.maximized_h = 0;
1009    bd->client.netwm.state.shaded = 0;
1010    bd->client.netwm.state.skip_taskbar = 0;
1011    bd->client.netwm.state.skip_pager = 0;
1012    bd->client.netwm.state.hidden = 0;
1013    bd->client.netwm.state.fullscreen = 0;
1014    bd->client.netwm.state.stacking = 0;
1015
1016    ecore_x_netwm_window_state_get(bd->client.win, &state, &num);
1017    if (state)
1018      {
1019         for (i = 0; i < num; i++)
1020           {
1021              switch (state[i])
1022                {
1023                 case ECORE_X_WINDOW_STATE_ICONIFIED:
1024      /* Ignore */
1025                   break;
1026
1027                 case ECORE_X_WINDOW_STATE_MODAL:
1028                   bd->client.netwm.state.modal = 1;
1029                   break;
1030
1031                 case ECORE_X_WINDOW_STATE_STICKY:
1032                   bd->client.netwm.state.sticky = 1;
1033                   break;
1034
1035                 case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
1036                   bd->client.netwm.state.maximized_v = 1;
1037                   break;
1038
1039                 case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
1040                   bd->client.netwm.state.maximized_h = 1;
1041                   break;
1042
1043                 case ECORE_X_WINDOW_STATE_SHADED:
1044                   bd->client.netwm.state.shaded = 1;
1045                   break;
1046
1047                 case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
1048                   bd->client.netwm.state.skip_taskbar = 1;
1049                   break;
1050
1051                 case ECORE_X_WINDOW_STATE_SKIP_PAGER:
1052                   bd->client.netwm.state.skip_pager = 1;
1053                   break;
1054
1055                 case ECORE_X_WINDOW_STATE_HIDDEN:
1056                   bd->client.netwm.state.hidden = 1;
1057                   break;
1058
1059                 case ECORE_X_WINDOW_STATE_FULLSCREEN:
1060                   bd->client.netwm.state.fullscreen = 1;
1061                   break;
1062
1063                 case ECORE_X_WINDOW_STATE_ABOVE:
1064                   bd->client.netwm.state.stacking = E_STACKING_ABOVE;
1065                   break;
1066
1067                 case ECORE_X_WINDOW_STATE_BELOW:
1068                   bd->client.netwm.state.stacking = E_STACKING_BELOW;
1069                   break;
1070
1071                 case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
1072      /* FIXME */
1073                   break;
1074
1075                 case ECORE_X_WINDOW_STATE_UNKNOWN:
1076      /* Ignore */
1077                   break;
1078                }
1079           }
1080         free(state);
1081      }
1082 }
1083
1084 EAPI void
1085 e_hints_allowed_action_update(E_Border *bd   __UNUSED__,
1086                               Ecore_X_Action action)
1087 {
1088    switch (action)
1089      {
1090       case ECORE_X_ACTION_MOVE:
1091         break;
1092
1093       case ECORE_X_ACTION_RESIZE:
1094         break;
1095
1096       case ECORE_X_ACTION_MINIMIZE:
1097         break;
1098
1099       case ECORE_X_ACTION_SHADE:
1100         break;
1101
1102       case ECORE_X_ACTION_STICK:
1103         break;
1104
1105       case ECORE_X_ACTION_MAXIMIZE_HORZ:
1106         break;
1107
1108       case ECORE_X_ACTION_MAXIMIZE_VERT:
1109         break;
1110
1111       case ECORE_X_ACTION_FULLSCREEN:
1112         break;
1113
1114       case ECORE_X_ACTION_CHANGE_DESKTOP:
1115         break;
1116
1117       case ECORE_X_ACTION_CLOSE:
1118         break;
1119
1120       case ECORE_X_ACTION_ABOVE:
1121         break;
1122
1123       case ECORE_X_ACTION_BELOW:
1124         break;
1125      }
1126 }
1127
1128 EAPI void
1129 e_hints_allowed_action_get(E_Border *bd)
1130 {
1131    Ecore_X_Action *action;
1132    unsigned int i;
1133    unsigned int num;
1134
1135    bd->client.netwm.action.move = 0;
1136    bd->client.netwm.action.resize = 0;
1137    bd->client.netwm.action.minimize = 0;
1138    bd->client.netwm.action.shade = 0;
1139    bd->client.netwm.action.stick = 0;
1140    bd->client.netwm.action.maximized_h = 0;
1141    bd->client.netwm.action.maximized_v = 0;
1142    bd->client.netwm.action.fullscreen = 0;
1143    bd->client.netwm.action.change_desktop = 0;
1144    bd->client.netwm.action.close = 0;
1145
1146    ecore_x_netwm_allowed_action_get(bd->client.win, &action, &num);
1147    if (action)
1148      {
1149         for (i = 0; i < num; i++)
1150           {
1151              switch (action[i])
1152                {
1153                 case ECORE_X_ACTION_MOVE:
1154                   bd->client.netwm.action.move = 1;
1155                   break;
1156
1157                 case ECORE_X_ACTION_RESIZE:
1158                   bd->client.netwm.action.resize = 1;
1159                   break;
1160
1161                 case ECORE_X_ACTION_MINIMIZE:
1162                   bd->client.netwm.action.minimize = 1;
1163                   break;
1164
1165                 case ECORE_X_ACTION_SHADE:
1166                   bd->client.netwm.action.shade = 1;
1167                   break;
1168
1169                 case ECORE_X_ACTION_STICK:
1170                   bd->client.netwm.action.stick = 1;
1171                   break;
1172
1173                 case ECORE_X_ACTION_MAXIMIZE_HORZ:
1174                   bd->client.netwm.action.maximized_h = 1;
1175                   break;
1176
1177                 case ECORE_X_ACTION_MAXIMIZE_VERT:
1178                   bd->client.netwm.action.maximized_v = 1;
1179                   break;
1180
1181                 case ECORE_X_ACTION_FULLSCREEN:
1182                   bd->client.netwm.action.fullscreen = 1;
1183                   break;
1184
1185                 case ECORE_X_ACTION_CHANGE_DESKTOP:
1186                   bd->client.netwm.action.change_desktop = 1;
1187                   break;
1188
1189                 case ECORE_X_ACTION_CLOSE:
1190                   bd->client.netwm.action.close = 1;
1191                   break;
1192
1193                 case ECORE_X_ACTION_ABOVE:
1194                   break;
1195
1196                 case ECORE_X_ACTION_BELOW:
1197                   break;
1198                }
1199           }
1200         free(action);
1201      }
1202 }
1203
1204 EAPI void
1205 e_hints_window_visible_set(E_Border *bd)
1206 {
1207    if (bd->client.icccm.state != ECORE_X_WINDOW_STATE_HINT_NORMAL)
1208      {
1209         ecore_x_icccm_state_set(bd->client.win, ECORE_X_WINDOW_STATE_HINT_NORMAL);
1210         bd->client.icccm.state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
1211      }
1212    if (bd->client.netwm.state.hidden)
1213      {
1214         bd->client.netwm.update.state = 1;
1215         bd->client.netwm.state.hidden = 0;
1216         bd->changed = 1;
1217      }
1218 }
1219
1220 EAPI void
1221 e_hints_window_iconic_set(E_Border *bd)
1222 {
1223    if (bd->client.icccm.state != ECORE_X_WINDOW_STATE_HINT_ICONIC)
1224      {
1225         ecore_x_icccm_state_set(bd->client.win, ECORE_X_WINDOW_STATE_HINT_ICONIC);
1226         bd->client.icccm.state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
1227      }
1228    if (!bd->client.netwm.state.hidden)
1229      {
1230         bd->client.netwm.update.state = 1;
1231         bd->client.netwm.state.hidden = 1;
1232         bd->changed = 1;
1233      }
1234 }
1235
1236 EAPI void
1237 e_hints_window_hidden_set(E_Border *bd)
1238 {
1239    if (bd->client.icccm.state != ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
1240      {
1241         ecore_x_icccm_state_set(bd->client.win, ECORE_X_WINDOW_STATE_HINT_WITHDRAWN);
1242         bd->client.icccm.state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
1243      }
1244    if (bd->client.netwm.state.hidden)
1245      {
1246         bd->client.netwm.update.state = 1;
1247         bd->client.netwm.state.hidden = 0;
1248         bd->changed = 1;
1249      }
1250 }
1251
1252 EAPI void
1253 e_hints_window_shaded_set(E_Border *bd,
1254                           int       on)
1255 {
1256    if ((!bd->client.netwm.state.shaded) && (on))
1257      {
1258         bd->client.netwm.update.state = 1;
1259         bd->client.netwm.state.shaded = 1;
1260         bd->changed = 1;
1261      }
1262    else if ((bd->client.netwm.state.shaded) && (!on))
1263      {
1264         bd->client.netwm.update.state = 1;
1265         bd->client.netwm.state.shaded = 0;
1266         bd->changed = 1;
1267      }
1268 }
1269
1270 EAPI void
1271 e_hints_window_shade_direction_set(E_Border   *bd,
1272                                    E_Direction dir)
1273 {
1274    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_SHADE_DIRECTION, &dir, 1);
1275 }
1276
1277 EAPI E_Direction
1278 e_hints_window_shade_direction_get(E_Border *bd)
1279 {
1280    int ret;
1281    E_Direction dir;
1282
1283    ret = ecore_x_window_prop_card32_get(bd->client.win,
1284                                         E_ATOM_SHADE_DIRECTION,
1285                                         &dir, 1);
1286    if (ret == 1)
1287      return dir;
1288
1289    return E_DIRECTION_UP;
1290 }
1291
1292 EAPI void
1293 e_hints_window_size_set(E_Border *bd)
1294 {
1295    unsigned int sizes[4];
1296
1297    sizes[0] = bd->x;
1298    sizes[1] = bd->y;
1299    sizes[2] = bd->w;
1300    sizes[3] = bd->h;
1301    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_BORDER_SIZE, sizes, 4);
1302 }
1303
1304 EAPI void
1305 e_hints_window_size_unset(E_Border *bd)
1306 {
1307    ecore_x_window_prop_property_del(bd->client.win, E_ATOM_BORDER_SIZE);
1308 }
1309
1310 EAPI int
1311 e_hints_window_size_get(E_Border *bd)
1312 {
1313    int ret;
1314    unsigned int sizes[4];
1315
1316    memset(sizes, 0, sizeof(sizes));
1317    ret = ecore_x_window_prop_card32_get(bd->client.win, E_ATOM_BORDER_SIZE,
1318                                         sizes, 4);
1319    if (ret != 4)
1320      return 0;
1321
1322    bd->x = sizes[0];
1323    bd->y = sizes[1];
1324    bd->w = sizes[2];
1325    bd->h = sizes[3];
1326
1327    return 1;
1328 }
1329
1330 EAPI void
1331 e_hints_window_maximized_set(E_Border *bd,
1332                              int       horizontal,
1333                              int       vertical)
1334 {
1335    if ((horizontal) && (!bd->client.netwm.state.maximized_h))
1336      {
1337         bd->client.netwm.update.state = 1;
1338         bd->client.netwm.state.maximized_h = 1;
1339         bd->changed = 1;
1340      }
1341    else if ((!horizontal) && (bd->client.netwm.state.maximized_h))
1342      {
1343         bd->client.netwm.update.state = 1;
1344         bd->client.netwm.state.maximized_h = 0;
1345         bd->changed = 1;
1346      }
1347    if ((vertical) && (!bd->client.netwm.state.maximized_v))
1348      {
1349         bd->client.netwm.update.state = 1;
1350         bd->client.netwm.state.maximized_v = 1;
1351         bd->changed = 1;
1352      }
1353    else if ((!vertical) && (bd->client.netwm.state.maximized_v))
1354      {
1355         bd->client.netwm.update.state = 1;
1356         bd->client.netwm.state.maximized_v = 0;
1357         bd->changed = 1;
1358      }
1359 }
1360
1361 EAPI void
1362 e_hints_window_fullscreen_set(E_Border *bd,
1363                               int       on)
1364 {
1365    if ((!bd->client.netwm.state.fullscreen) && (on))
1366      {
1367         bd->client.netwm.update.state = 1;
1368         bd->client.netwm.state.fullscreen = 1;
1369         bd->changed = 1;
1370      }
1371    else if ((bd->client.netwm.state.fullscreen) && (!on))
1372      {
1373         bd->client.netwm.update.state = 1;
1374         bd->client.netwm.state.fullscreen = 0;
1375         bd->changed = 1;
1376      }
1377 }
1378
1379 EAPI void
1380 e_hints_window_sticky_set(E_Border *bd,
1381                           int       on)
1382 {
1383    if ((!bd->client.netwm.state.sticky) && (on))
1384      {
1385         bd->client.netwm.update.state = 1;
1386         bd->client.netwm.state.sticky = 1;
1387         bd->changed = 1;
1388      }
1389    else if ((bd->client.netwm.state.sticky) && (!on))
1390      {
1391         bd->client.netwm.update.state = 1;
1392         bd->client.netwm.state.sticky = 0;
1393         bd->changed = 1;
1394      }
1395 }
1396
1397 EAPI void
1398 e_hints_window_stacking_set(E_Border  *bd,
1399                             E_Stacking stacking)
1400 {
1401    if (bd->client.netwm.state.stacking == stacking) return;
1402    bd->client.netwm.update.state = 1;
1403    bd->client.netwm.state.stacking = stacking;
1404    bd->changed = 1;
1405 }
1406
1407 EAPI void
1408 e_hints_window_desktop_set(E_Border *bd)
1409 {
1410    /* This function is only called when really changing desktop,
1411     * so just set the property and don't care about the roundtrip.
1412     */
1413      unsigned int deskpos[2];
1414
1415      /* if valgrind complains here it is complaining bd->client.netwm.desktop
1416       * is an uninitialised variable - but it isn't. it can't be. its part of
1417       * a calloc()'d struct and thus has to have been set to 0. hell even
1418       * e_border.c explicitly sets it to 0 on creation of the border object.
1419       */
1420      deskpos[0] = bd->desk->x;
1421      deskpos[1] = bd->desk->y;
1422      ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_DESK, deskpos, 2);
1423
1424      if (strcmp(bd->desk->window_profile,
1425                 e_config->desktop_default_window_profile) != 0)
1426        {
1427           ecore_x_e_window_profile_set(bd->client.win,
1428                                        bd->desk->window_profile);
1429        }
1430
1431 #if 0
1432      ecore_x_netwm_desktop_set(bd->client.win, current);
1433 #endif
1434      bd->client.netwm.desktop = (bd->desk->y * bd->zone->desk_x_count) + bd->desk->x;
1435 }
1436
1437 EAPI void
1438 e_hints_window_e_state_get(E_Border *bd)
1439 {
1440    /* Remember to update the count if we add more states! */
1441    Ecore_X_Atom state[1];
1442    int num = 0, i = 0;
1443    int size = 0;
1444
1445    memset(state, 0, sizeof(state));
1446
1447    /* ugly, but avoids possible future overflow if more states are added */
1448    size = (sizeof(state) / sizeof(state[0]));
1449
1450    num = 
1451      ecore_x_window_prop_card32_get(bd->client.win, E_ATOM_WINDOW_STATE,
1452                                     state, size);
1453    if (!num) return;
1454
1455    for (i = 0; (i < num) && (i < size); i++)
1456      {
1457         if (state[i] == E_ATOM_WINDOW_STATE_CENTERED)
1458           bd->client.e.state.centered = 1;
1459      }
1460 }
1461
1462 EAPI void
1463 e_hints_window_e_state_set(E_Border *bd __UNUSED__)
1464 {
1465    /* TODO */
1466 }
1467
1468 EAPI void
1469 e_hints_window_qtopia_soft_menu_get(E_Border *bd)
1470 {
1471    unsigned int val;
1472
1473    if (ecore_x_window_prop_card32_get(bd->client.win, ATM__QTOPIA_SOFT_MENU, &val, 1))
1474      bd->client.qtopia.soft_menu = val;
1475    else
1476      bd->client.qtopia.soft_menu = 0;
1477 }
1478
1479 EAPI void
1480 e_hints_window_qtopia_soft_menus_get(E_Border *bd)
1481 {
1482    unsigned int val;
1483
1484    if (ecore_x_window_prop_card32_get(bd->client.win, ATM__QTOPIA_SOFT_MENUS, &val, 1))
1485      bd->client.qtopia.soft_menus = val;
1486    else
1487      bd->client.qtopia.soft_menus = 0;
1488 }
1489
1490 EAPI void
1491 e_hints_window_virtual_keyboard_state_get(E_Border *bd)
1492 {
1493    bd->client.vkbd.state = ecore_x_e_virtual_keyboard_state_get(bd->client.win);
1494 }
1495
1496 EAPI void
1497 e_hints_window_virtual_keyboard_get(E_Border *bd)
1498 {
1499    bd->client.vkbd.vkbd = ecore_x_e_virtual_keyboard_get(bd->client.win);
1500 }
1501
1502 EAPI void
1503 e_hints_openoffice_gnome_fake(Ecore_X_Window root)
1504 {
1505    const char *string = "ATM_GNOME_SM_PROXY";
1506
1507    ecore_x_window_prop_property_set(root, ATM_GNOME_SM_PROXY, ECORE_X_ATOM_STRING,
1508                                     8, (void *)string, strlen(string));
1509 }
1510
1511 EAPI void
1512 e_hints_openoffice_kde_fake(Ecore_X_Window root)
1513 {
1514    Ecore_X_Window win2;
1515
1516    win2 = ecore_x_window_new(root, -20, -20, 1, 1);
1517    ecore_x_netwm_wm_identify(root, win2, "KWin");
1518 }
1519
1520 EAPI void
1521 e_hints_scale_update(void)
1522 {
1523    Ecore_X_Window *roots = NULL;
1524    int i, num;
1525    unsigned int scale;
1526
1527    roots = ecore_x_window_root_list(&num);
1528    if (roots)
1529      {
1530         scale = e_scale * 1000;
1531         for (i = 0; i < num; i++)
1532           ecore_x_window_prop_card32_set(roots[i], ATM_ENLIGHTENMENT_SCALE, &scale, 1);
1533         free(roots);
1534      }
1535 }
1536