chiark / gitweb /
Imported Debian patch 1.0.0-6
[e16] / src / hints.c
1 /*
2  * Copyright (C) 2003-2008 Kim Woelders
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies of the Software, its documentation and marketing & publicity
13  * materials, and acknowledgment shall be given in the documentation, materials
14  * and software packages that this Software was used.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 /*
24  * Feeble attempt to collect hint stuff in one place
25  */
26 #include "E.h"
27 #include "borders.h"            /* FIXME - Should not be here */
28 #include "desktops.h"           /* FIXME - Should not be here */
29 #include "e16-ecore_hints.h"
30 #include "events.h"
31 #include "ewins.h"
32 #include "hints.h"
33 #include "xwin.h"
34 #include <X11/Xatom.h>
35
36 #define N_ITEMS(x) (sizeof(x)/sizeof(x[0]))
37
38 static const char  *const atoms_misc_names[] = {
39    /* Misc atoms */
40    "MANAGER",
41
42    /* Root background atoms */
43    "_XROOTPMAP_ID",
44    "_XROOTCOLOR_PIXEL",
45
46    /* E16 atoms */
47    "ENLIGHTENMENT_VERSION",
48
49    "ENLIGHTENMENT_COMMS",
50    "ENL_MSG",
51
52    "ENL_INTERNAL_AREA_DATA",
53    "ENL_INTERNAL_DESK_DATA",
54    "ENL_WIN_DATA",
55    "ENL_WIN_BORDER"
56 };
57
58 unsigned int        atoms_misc[10];
59
60 void
61 AtomListIntern(const char *const *names, unsigned int num, unsigned int *atoms)
62 {
63 #if SIZEOF_INT == SIZEOF_LONG
64    XInternAtoms(disp, (char **)names, num, False, (Atom *) atoms);
65 #else
66    unsigned int        i;
67    Atom               *_atoms;
68
69    _atoms = EMALLOC(Atom, num);
70    if (!_atoms)
71       return;
72
73    XInternAtoms(disp, (char **)names, num, False, _atoms);
74    for (i = 0; i < num; i++)
75       atoms[i] = _atoms[i];
76
77    Efree(_atoms);
78 #endif
79 }
80
81 void
82 HintsInit(void)
83 {
84    Window              win;
85
86    AtomListIntern(atoms_misc_names, N_ITEMS(atoms_misc_names), atoms_misc);
87
88    win = XCreateSimpleWindow(disp, WinGetXwin(VROOT), -200, -200, 5, 5,
89                              0, 0, 0);
90
91    ICCCM_Init();
92    MWM_SetInfo();
93 #if ENABLE_GNOME
94    GNOME_SetHints(win);
95 #endif
96    EWMH_Init(win);
97
98    ecore_x_window_prop_string_set(WinGetXwin(VROOT), E16_ATOM_VERSION,
99                                   e_wm_version);
100
101    if (Mode.wm.window)
102      {
103         HintsSetWindowName(VROOT, "Enlightenment");
104         HintsSetWindowClass(VROOT, "Virtual-Root", "Enlightenment");
105      }
106
107    Mode.root.ext_pmap = HintsGetRootPixmap(VROOT);
108    Mode.root.ext_pmap_valid = EDrawableCheck(Mode.root.ext_pmap, 0);
109 }
110
111 /*
112  * Functions that set X11-properties from E-internals
113  */
114
115 void
116 HintsSetRootHints(Win win __UNUSED__)
117 {
118    /* Nothing done here for now */
119 }
120
121 void
122 HintsSetClientList(void)
123 {
124 #if ENABLE_GNOME
125    GNOME_SetClientList();
126 #endif
127    EWMH_SetClientList();
128    EWMH_SetClientStacking();
129 }
130
131 void
132 HintsSetClientStacking(void)
133 {
134    EWMH_SetClientStacking();
135 }
136
137 void
138 HintsSetDesktopConfig(void)
139 {
140 #if ENABLE_GNOME
141    GNOME_SetDeskCount();
142    GNOME_SetDeskNames();
143 #endif
144    EWMH_SetDesktopCount();
145    EWMH_SetDesktopRoots();
146    EWMH_SetDesktopNames();
147    EWMH_SetWorkArea();
148 }
149
150 void
151 HintsSetViewportConfig(void)
152 {
153 #if ENABLE_GNOME
154    GNOME_SetAreaCount();
155 #endif
156    EWMH_SetDesktopSize();
157 }
158
159 void
160 HintsSetCurrentDesktop(void)
161 {
162 #if ENABLE_GNOME
163    GNOME_SetCurrentDesk();
164 #endif
165    EWMH_SetCurrentDesktop();
166    HintsSetDesktopViewport();
167 }
168
169 void
170 HintsSetDesktopViewport(void)
171 {
172 #if ENABLE_GNOME
173    GNOME_SetCurrentArea();
174 #endif
175    EWMH_SetDesktopViewport();
176 }
177
178 void
179 HintsSetActiveWindow(Window win)
180 {
181    EWMH_SetActiveWindow(win);
182 }
183
184 void
185 HintsSetWindowName(Win win, const char *name)
186 {
187    if (!name)
188       return;
189
190    ecore_x_icccm_title_set(WinGetXwin(win), name);
191
192    EWMH_SetWindowName(WinGetXwin(win), name);
193 }
194
195 void
196 HintsSetWindowClass(Win win, const char *name, const char *clss)
197 {
198    if (!name)
199       name = "NoName";
200    if (!clss)
201       clss = "NoClass";
202
203    ecore_x_icccm_name_class_set(WinGetXwin(win), name, clss);
204 }
205
206 void
207 HintsSetWindowDesktop(const EWin * ewin)
208 {
209 #if ENABLE_GNOME
210    GNOME_SetEwinDesk(ewin);
211 #endif
212    EWMH_SetWindowDesktop(ewin);
213 }
214
215 void
216 HintsSetWindowArea(const EWin * ewin __UNUSED__)
217 {
218 #if ENABLE_GNOME
219    GNOME_SetEwinArea(ewin);
220 #endif
221 }
222
223 void
224 HintsSetWindowState(const EWin * ewin)
225 {
226 #if ENABLE_GNOME
227    GNOME_SetHint(ewin);
228 #endif
229    EWMH_SetWindowState(ewin);
230    EWMH_SetWindowActions(ewin);
231 }
232
233 void
234 HintsSetWindowOpacity(const EWin * ewin)
235 {
236    EWMH_SetWindowOpacity(ewin);
237 }
238
239 void
240 HintsSetWindowBorder(const EWin * ewin)
241 {
242    EWMH_SetWindowBorder(ewin);
243 }
244
245 /*
246  * Functions that set E-internals from X11-properties
247  */
248
249 void
250 HintsGetWindowHints(EWin * ewin)
251 {
252 #if ENABLE_GNOME
253    GNOME_GetHints(ewin, 0);
254 #endif
255    EWMH_GetWindowHints(ewin);
256 }
257
258 /*
259  * Functions that delete X11-properties
260  */
261
262 void
263 HintsDelWindowHints(const EWin * ewin)
264 {
265 #if ENABLE_GNOME
266    GNOME_DelHints(ewin);
267 #endif
268    EWMH_DelWindowHints(ewin);
269 }
270
271 /*
272  * Functions processing received X11 messages
273  */
274
275 void
276 HintsProcessPropertyChange(EWin * ewin, XEvent * ev)
277 {
278    if (ICCCM_ProcessPropertyChange(ewin, ev->xproperty.atom))
279       return;
280    if (EWMH_ProcessPropertyChange(ewin, ev->xproperty.atom))
281       return;
282 #if 0                           /* No! - ENABLE_GNOME */
283    if (GNOME_GetHints(ewin, ev->xproperty.atom))
284       return;
285 #endif
286 #if 0
287    if (EDebug(1))
288      {
289         Eprintf("HintsProcessPropertyChange:\n");
290         EventShow(ev);
291      }
292 #endif
293 }
294
295 void
296 HintsProcessClientClientMessage(EWin * ewin, XClientMessageEvent * event)
297 {
298    if (ICCCM_ProcessClientClientMessage(ewin, event))
299       return;
300    if (EWMH_ProcessClientClientMessage(ewin, event))
301       return;
302 #if ENABLE_GNOME
303    if (GNOME_ProcessClientClientMessage(ewin, event))
304       return;
305 #endif
306    if (EDebug(1))
307      {
308         Eprintf("HintsProcessClientClientMessage:\n");
309         EventShow((XEvent *) event);
310      }
311 }
312
313 void
314 HintsProcessRootClientMessage(XClientMessageEvent * event)
315 {
316    if (ICCCM_ProcessRootClientMessage(event))
317       return;
318    if (EWMH_ProcessRootClientMessage(event))
319       return;
320 #if ENABLE_GNOME
321    if (GNOME_ProcessRootClientMessage(event))
322       return;
323 #endif
324    if (EDebug(1))
325      {
326         Eprintf("HintsProcessRootClientMessage:\n");
327         EventShow((XEvent *) event);
328      }
329 }
330
331 Pixmap
332 HintsGetRootPixmap(Win win)
333 {
334    Ecore_X_Pixmap      pm;
335    int                 num;
336
337    pm = None;
338    num =
339       ecore_x_window_prop_xid_get(WinGetXwin(win), E_XROOTPMAP_ID, XA_PIXMAP,
340                                   &pm, 1);
341
342    return pm;
343 }
344
345 void
346 HintsSetRootInfo(Win win, Pixmap pmap, unsigned int color)
347 {
348    Ecore_X_Pixmap      pm;
349
350    pm = pmap;
351    ecore_x_window_prop_xid_set(WinGetXwin(win), E_XROOTPMAP_ID, XA_PIXMAP, &pm,
352                                1);
353
354    ecore_x_window_prop_card32_set(WinGetXwin(win), E_XROOTCOLOR_PIXEL, &color,
355                                   1);
356 }
357
358 typedef union {
359    struct {
360       unsigned            version:8;
361       unsigned            rsvd:22;
362       unsigned            docked:1;
363       unsigned            iconified:1;
364    } b;
365    int                 all:32;
366 } EWinInfoFlags;
367
368 #define ENL_DATA_ITEMS      12
369 #define ENL_DATA_VERSION     0
370
371 void
372 EHintsSetInfo(const EWin * ewin)
373 {
374    int                 c[ENL_DATA_ITEMS];
375    unsigned int        flags[2];
376    EWinInfoFlags       f;
377
378    if (EwinIsInternal(ewin))
379       return;
380
381    f.all = 0;
382    f.b.version = ENL_DATA_VERSION;
383    f.b.docked = ewin->state.docked;
384    f.b.iconified = ewin->state.iconified;
385    c[0] = f.all;
386
387    EwinFlagsEncode(ewin, flags);
388    c[1] = flags[0];
389    c[2] = flags[1];
390
391    c[3] = ewin->save_max.x;
392    c[4] = ewin->save_max.y;
393    c[5] = ewin->save_max.w;
394    c[6] = ewin->save_max.h;
395    c[7] = ewin->save_fs.x;
396    c[8] = ewin->save_fs.y;
397    c[9] = ewin->save_fs.w;
398    c[10] = ewin->save_fs.h;
399    c[11] = ewin->save_fs.layer;
400
401    ecore_x_window_prop_card32_set(EwinGetClientXwin(ewin), E16_ATOM_WIN_DATA,
402                                   (unsigned int *)c, ENL_DATA_ITEMS);
403
404    ecore_x_window_prop_string_set(EwinGetClientXwin(ewin), E16_ATOM_WIN_BORDER,
405                                   ewin->normal_border->name);
406
407    if (EDebug(EDBUG_TYPE_SNAPS))
408       Eprintf("Snap set einf  %#lx: %4d+%4d %4dx%4d: %s\n",
409               EwinGetClientXwin(ewin), ewin->client.x, ewin->client.y,
410               ewin->client.w, ewin->client.h, EwinGetTitle(ewin));
411 }
412
413 void
414 EHintsGetInfo(EWin * ewin)
415 {
416    char               *str;
417    int                 num;
418    int                 c[ENL_DATA_ITEMS + 1];
419    unsigned int        flags[2];
420    EWinInfoFlags       f;
421
422    if (EwinIsInternal(ewin))
423       return;
424
425    num =
426       ecore_x_window_prop_card32_get(EwinGetClientXwin(ewin), E16_ATOM_WIN_DATA,
427                                      (unsigned int *)c, ENL_DATA_ITEMS + 1);
428    if (num < 0)
429       return;
430
431    ewin->state.identified = 1;
432    ewin->state.placed = 1;
433
434    if (num < 2)
435       return;
436
437    f.all = c[0];
438    if (f.b.version != ENL_DATA_VERSION)
439       return;
440    ewin->icccm.start_iconified = f.b.iconified;
441    ewin->state.docked = f.b.docked;
442
443    flags[0] = c[1];
444    flags[1] = c[2];
445    EwinFlagsDecode(ewin, flags);
446
447    if (num == ENL_DATA_ITEMS)
448      {
449         ewin->save_max.x = c[3];
450         ewin->save_max.y = c[4];
451         ewin->save_max.w = c[5];
452         ewin->save_max.h = c[6];
453         ewin->save_fs.x = c[7];
454         ewin->save_fs.y = c[8];
455         ewin->save_fs.w = c[9];
456         ewin->save_fs.h = c[10];
457         ewin->save_fs.layer = c[11];
458      }
459
460    str =
461       ecore_x_window_prop_string_get(EwinGetClientXwin(ewin),
462                                      E16_ATOM_WIN_BORDER);
463    if (str)
464       EwinBorderSetInitially(ewin, str);
465    Efree(str);
466
467    if (EDebug(EDBUG_TYPE_SNAPS))
468       Eprintf("Snap get einf  %#lx: %4d+%4d %4dx%4d: %s\n",
469               EwinGetClientXwin(ewin), ewin->client.x, ewin->client.y,
470               ewin->client.w, ewin->client.h, EwinGetTitle(ewin));
471 }
472
473 void
474 EHintsSetDeskInfo(void)
475 {
476    int                 i, ax, ay, n_desks;
477    unsigned int       *c;
478
479    if (!DesksGetCurrent())      /* Quit if current desk isn't assigned yet */
480       return;
481
482    n_desks = DesksGetNumber();
483    if (n_desks <= 0)
484       return;
485
486    c = EMALLOC(unsigned int, 2 * n_desks);
487    if (!c)
488       return;
489
490    for (i = 0; i < n_desks; i++)
491      {
492         DeskGetArea(DeskGet(i), &ax, &ay);
493         c[(i * 2)] = ax;
494         c[(i * 2) + 1] = ay;
495      }
496
497    ecore_x_window_prop_card32_set(WinGetXwin(VROOT),
498                                   E16_ATOM_INTERNAL_AREA_DATA, c, 2 * n_desks);
499
500    c[0] = DesksGetCurrentNum();
501    ecore_x_window_prop_card32_set(WinGetXwin(VROOT),
502                                   E16_ATOM_INTERNAL_DESK_DATA, c, 1);
503
504    Efree(c);
505
506    if (Mode.root.ext_pmap_valid)
507      {
508         HintsSetRootInfo(VROOT, Mode.root.ext_pmap, 0);
509         ESetWindowBackgroundPixmap(VROOT, Mode.root.ext_pmap);
510      }
511 }
512
513 void
514 EHintsGetDeskInfo(void)
515 {
516    unsigned int       *c;
517    int                 num, i, n_desks;
518
519    n_desks = DesksGetNumber();
520    c = EMALLOC(unsigned int, 2 * n_desks);
521
522    if (!c)
523       return;
524
525    num = ecore_x_window_prop_card32_get(WinGetXwin(VROOT),
526                                         E16_ATOM_INTERNAL_AREA_DATA,
527                                         c, 2 * n_desks);
528    if (num > 0)
529      {
530         for (i = 0; i < (num / 2); i++)
531            DeskSetArea(DeskGet(i), c[(i * 2)], c[(i * 2) + 1]);
532      }
533
534    num = ecore_x_window_prop_card32_get(WinGetXwin(VROOT),
535                                         E16_ATOM_INTERNAL_DESK_DATA, c, 1);
536    if (num > 0)
537      {
538         DesksSetCurrent(DeskGet(c[0]));
539      }
540    else
541      {
542         /* Used to test if we should run cmd_init */
543         Mode.wm.session_start = 1;
544      }
545
546    Efree(c);
547 }
548
549 void
550 EHintsSetInfoOnAll(void)
551 {
552    int                 i, num;
553    EWin               *const *lst;
554
555    if (EDebug(EDBUG_TYPE_SESSION))
556       Eprintf("SetEInfoOnAll\n");
557
558    lst = EwinListGetAll(&num);
559    for (i = 0; i < num; i++)
560       if (!EwinIsInternal(lst[i]))
561          EHintsSetInfo(lst[i]);
562
563    EHintsSetDeskInfo();
564 }
565
566 /*
567  * Selections.
568  */
569
570 struct _selection {
571    Atom                atom;
572    Time                time;
573    Win                 win;
574    EventCallbackFunc  *func;
575    void               *data;
576 };
577
578 ESelection         *
579 SelectionAcquire(const char *name, EventCallbackFunc * func, void *data)
580 {
581    ESelection         *sel;
582    char                buf[128];
583
584    sel = ECALLOC(ESelection, 1);
585    if (!sel)
586       return sel;
587
588    Esnprintf(buf, sizeof(buf), "%s%d", name, Dpy.screen);
589
590    sel->atom = EInternAtom(buf);
591    sel->time = EGetTimestamp();
592    sel->win = ECreateEventWindow(VROOT, -100, -100, 1, 1);
593
594    sel->func = func;
595    sel->data = data;
596
597    XSetSelectionOwner(disp, sel->atom, WinGetXwin(sel->win), sel->time);
598    if (XGetSelectionOwner(disp, sel->atom) != WinGetXwin(sel->win))
599      {
600         DialogOK(_("Selection Error!"), _("Could not acquire selection: %s"),
601                  buf);
602         EDestroyWindow(sel->win);
603         Efree(sel);
604         return NULL;
605      }
606
607    if (sel->func)
608      {
609         ESelectInput(sel->win, SubstructureNotifyMask);
610         EventCallbackRegister(sel->win, 0, sel->func, sel->data);
611      }
612
613    ecore_x_client_message32_send(WinGetXwin(VROOT), E_XA_MANAGER,
614                                  StructureNotifyMask, CurrentTime, sel->atom,
615                                  WinGetXwin(sel->win), 0, 0);
616
617    if (EDebug(EDBUG_TYPE_SELECTION))
618       Eprintf("Window %#lx is now %s owner, time=%lu\n",
619               WinGetXwin(sel->win), buf, sel->time);
620
621    return sel;
622 }
623
624 void
625 SelectionRelease(ESelection * sel)
626 {
627    if (!sel)
628       return;
629
630    if (EDebug(EDBUG_TYPE_SELECTION))
631       Eprintf("Window %#lx is no longer %s owner\n",
632               WinGetXwin(sel->win), XGetAtomName(disp, sel->atom));
633
634    XSetSelectionOwner(disp, sel->atom, None, sel->time);
635    if (sel->func)
636      {
637         EventCallbackUnregister(sel->win, 0, sel->func, sel->data);
638      }
639    EDestroyWindow(sel->win);
640    Efree(sel);
641 }