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