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