chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / src / eobj.c
1 /*
2  * Copyright (C) 2004-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 #include "E.h"
24 #include "desktops.h"
25 #include "e16-ecore_hints.h"
26 #include "ecompmgr.h"
27 #include "eobj.h"
28 #include "ewins.h"              /* FIXME - Should not be here */
29 #include "hints.h"
30 #include "xwin.h"
31
32 int
33 OpacityFix(int op, int op_0)
34 {
35    if (op <= 0)
36       op = op_0;
37    else if (op > 255)
38       op = 100;
39    else if (op > 100)           /* Hack to convert old 0-255 range */
40       op = (100 * op) / 255;
41    return op;
42 }
43
44 unsigned int
45 OpacityFromPercent(int opx)
46 {
47    unsigned int        op = (unsigned int)opx;
48
49    /* op is 0-100, extend to 32 bit */
50    /* op <= 0 and op > 100 is mapped to 100 (opaque) */
51    if (op >= 100)
52       return 0xffffffff;
53    return op * 42949672;
54 }
55
56 int
57 OpacityToPercent(unsigned int opacity)
58 {
59    return (int)(opacity / 42949672);
60 }
61
62 void
63 EobjSetLayer(EObj * eo, int layer)
64 {
65    int                 ilayer = eo->ilayer;
66
67    eo->layer = layer;
68    /*
69     * For usual EWin's the internal layer is the "old" E-layer * 10.
70     *
71     * Internal layers:
72     *   0: Root
73     *   3: Desktop type apps
74     *   5: Below buttons
75     *  10: Lowest ewins
76     *  15: Normal buttons
77     *  20: Normal below ewins
78     *  40: Normal ewins
79     *  60: Above ewins
80     *  75: Above buttons
81     *  80: Ontop ewins
82     * 100: E-Dialogs
83     * 512-: Floating windows
84     * + 0: Virtual desktops
85     * +30: E-Menus
86     * +40: Override redirects
87     * +40: E-Tooltips
88     */
89
90    switch (eo->type)
91      {
92      case EOBJ_TYPE_EWIN:
93         eo->ilayer = 10 * eo->layer;
94         if (eo->ilayer == 0)
95            eo->ilayer = 3;
96         break;
97
98      case EOBJ_TYPE_BUTTON:
99         if (eo->layer > 0)
100            eo->ilayer = 75;     /* Ontop */
101         else if (eo->layer == 0)
102            eo->ilayer = 15;     /* Normal */
103         else if (eo->layer < 0)
104            eo->ilayer = 5;      /* Below */
105         if (eo->layer > 0 && eo->sticky)
106            eo->floating = 1;
107         break;
108
109      default:
110         eo->ilayer = 10 * eo->layer;
111         break;
112      }
113
114    if (eo->floating)
115       eo->ilayer |= 512;
116    else
117       eo->ilayer &= ~512;
118    if (eo->ghost)
119       eo->ilayer |= 1024;
120
121    if (eo->ilayer != ilayer)
122       EobjRaise(eo);
123 }
124
125 void
126 EobjSetFloating(EObj * eo, int floating)
127 {
128    if (floating == eo->floating)
129       return;
130
131 #if 0
132    switch (eo->type)
133      {
134      default:
135         break;
136      case EOBJ_TYPE_EWIN:
137         if (floating > 1)
138            eo->desk = 0;
139         break;
140      }
141 #endif
142
143    eo->floating = floating;
144    EobjSetLayer(eo, eo->layer);
145 }
146
147 #if 1                           /* FIXME - Remove */
148 int
149 EobjIsShaped(const EObj * eo)
150 {
151    switch (eo->type)
152      {
153      default:
154         return 0;               /* FIXME */
155      case EOBJ_TYPE_EWIN:
156         return ((EWin *) eo)->state.shaped;
157      }
158 }
159 #endif
160
161 #if USE_GLX
162 #define WINTYPE(t) ((t == EOBJ_TYPE_GLX) ? WIN_TYPE_GLX : WIN_TYPE_INTERNAL)
163 #else
164 #define WINTYPE(t) WIN_TYPE_INTERNAL
165 #endif
166
167 void
168 EobjInit(EObj * eo, int type, Win win, int x, int y, int w, int h,
169          int su, const char *name)
170 {
171    if (!eo->desk)
172       eo->desk = DeskGet(0);
173
174    if (!win)
175      {
176         if (type == EOBJ_TYPE_EVENT)
177           {
178              win = ECreateEventWindow(VROOT, x, y, w, h);
179              eo->inputonly = 1;
180           }
181         else
182           {
183              win = ECreateObjectWindow(EoGetWin(eo->desk), x, y, w, h, su,
184                                        WINTYPE(type), NULL);
185           }
186      }
187    eo->type = type;
188    eo->win = win;
189    eo->shaped = -1;
190    if (!win)
191       return;
192
193    if (type == EOBJ_TYPE_EXT)
194      {
195         eo->icccm.wm_name = ecore_x_icccm_title_get(WinGetXwin(win));
196         ecore_x_icccm_name_class_get(WinGetXwin(win),
197                                      &eo->icccm.wm_res_name,
198                                      &eo->icccm.wm_res_class);
199      }
200    else if (name)
201       eo->icccm.wm_name = Estrdup(name);
202    if (!eo->icccm.wm_name)
203       eo->icccm.wm_name = Estrdup("-?-");
204
205    if (type != EOBJ_TYPE_EWIN && type != EOBJ_TYPE_EXT)
206       HintsSetWindowName(EobjGetWin(eo), eo->icccm.wm_name);
207
208 #if USE_COMPOSITE
209    switch (type)
210      {
211      case EOBJ_TYPE_EVENT:
212      case EOBJ_TYPE_MISC_NR:
213      case EOBJ_TYPE_ROOT_BG:
214         eo->noredir = 1;
215         break;
216      }
217    ECompMgrWinNew(eo);
218 #endif
219    if (EobjGetXwin(eo) != WinGetXwin(VROOT))
220       EobjListStackAdd(eo, 1);
221
222    if (EDebug(EDBUG_TYPE_EWINS))
223       Eprintf("EobjInit: %#lx %s\n", EobjGetXwin(eo), EobjGetName(eo));
224 }
225
226 void
227 EobjFini(EObj * eo)
228 {
229    if (EDebug(EDBUG_TYPE_EWINS))
230       Eprintf("EobjFini: %#lx %s\n", EobjGetXwin(eo), EobjGetName(eo));
231
232    EobjListStackDel(eo);
233
234 #if USE_COMPOSITE
235    if (!eo->external)
236       eo->gone = 1;             /* Actually not yet (but soon) */
237
238    if (eo->cmhook)
239       ECompMgrWinDel(eo);
240 #endif
241
242    if (eo->external)
243       EUnregisterWindow(EobjGetWin(eo));
244    else
245       EDestroyWindow(EobjGetWin(eo));
246
247    Efree(eo->icccm.wm_name);
248    Efree(eo->icccm.wm_res_name);
249    Efree(eo->icccm.wm_res_class);
250 }
251
252 void
253 EobjDestroy(EObj * eo)
254 {
255    if (EDebug(EDBUG_TYPE_EWINS))
256       Eprintf("EobjDestroy: %#lx %s\n", EobjGetXwin(eo), EobjGetName(eo));
257
258    EobjFini(eo);
259
260    Efree(eo);
261 }
262
263 EObj               *
264 EobjWindowCreate(int type, int x, int y, int w, int h, int su, const char *name)
265 {
266    EObj               *eo;
267
268    eo = ECALLOC(EObj, 1);
269
270    eo->floating = 1;
271    EobjSetLayer(eo, 20);
272    EobjInit(eo, type, EobjGetWin(eo), x, y, w, h, su, name);
273    if (eo->win == NULL)
274      {
275         Efree(eo);
276         eo = NULL;
277      }
278
279    return eo;
280 }
281
282 void
283 EobjWindowDestroy(EObj * eo)
284 {
285    EobjDestroy(eo);
286 }
287
288 EObj               *
289 EobjRegister(Window xwin, int type)
290 {
291    EObj               *eo;
292    XWindowAttributes   attr;
293    Win                 win;
294
295    eo = EobjListStackFind(xwin);
296    if (eo)
297       return eo;
298
299    if (!XGetWindowAttributes(disp, xwin, &attr))
300       return NULL;
301
302    if (type == EOBJ_TYPE_EXT && !attr.override_redirect)
303       return NULL;
304
305    win = ERegisterWindow(xwin, &attr);
306    if (!win)
307       return NULL;
308
309    eo = ECALLOC(EObj, 1);
310    if (!eo)
311       return eo;
312
313 #if __cplusplus
314    if (attr.c_class == InputOnly)
315 #else
316    if (attr.class == InputOnly)
317 #endif
318       eo->inputonly = 1;
319
320    eo->external = 1;
321    eo->fade = 1;
322    eo->shadow = 1;
323
324    EobjInit(eo, type, win, attr.x, attr.y, attr.width, attr.height, 0, NULL);
325
326 #if 1                           /* FIXME - TBD */
327    if (type == EOBJ_TYPE_EXT)
328      {
329         eo->shaped = 0;         /* FIXME - Assume unshaped for now */
330         EobjSetFloating(eo, 1);
331         EobjSetLayer(eo, 4);
332      }
333 #endif
334 #if 0
335    Eprintf("EobjRegister: %#lx type=%d or=%d: %s\n", xwin, type,
336            attr.override_redirect, EobjGetName(eo));
337 #endif
338
339    return eo;
340 }
341
342 void
343 EobjUnregister(EObj * eo)
344 {
345 #if 0
346    Eprintf("EobjUnregister: %#lx type=%d: %s\n", eo->win, eo->type,
347            EobjGetName(eo));
348 #endif
349    EobjDestroy(eo);
350 }
351
352 void
353 EobjMap(EObj * eo, int raise)
354 {
355    if (eo->shown)
356       return;
357    eo->shown = 1;
358
359    if (raise)
360       EobjListStackRaise(eo, 0);
361
362    if (eo->stacked <= 0 || raise > 1)
363       DeskRestack(eo->desk);
364
365    if (eo->shaped < 0)
366       EobjShapeUpdate(eo, 0);
367
368    EMapWindow(EobjGetWin(eo));
369 #if USE_COMPOSITE
370    ECompMgrWinMap(eo);
371 #endif
372 }
373
374 void
375 EobjUnmap(EObj * eo)
376 {
377    if (!eo->shown)
378       return;
379
380 #if USE_COMPOSITE
381    if (eo->cmhook)
382       ECompMgrWinUnmap(eo);
383 #endif
384    EUnmapWindow(EobjGetWin(eo));
385    eo->shown = 0;
386 }
387
388 void
389 EobjMoveResize(EObj * eo, int x, int y, int w, int h)
390 {
391    int                 move, resize;
392
393    move = x != EobjGetX(eo) || y != EobjGetY(eo);
394    resize = w != EobjGetW(eo) || h != EobjGetH(eo);
395 #if USE_COMPOSITE
396    if (eo->type == EOBJ_TYPE_EWIN)
397      {
398         ECompMgrMoveResizeFix(eo, x, y, w, h);
399      }
400    else
401 #endif
402      {
403         EMoveResizeWindow(EobjGetWin(eo), x, y, w, h);
404      }
405 #if USE_COMPOSITE
406    if (eo->cmhook)
407       ECompMgrWinMoveResize(eo, move, resize, 0);
408 #endif
409 }
410
411 void
412 EobjMove(EObj * eo, int x, int y)
413 {
414    EobjMoveResize(eo, x, y, EobjGetW(eo), EobjGetH(eo));
415 }
416
417 void
418 EobjResize(EObj * eo, int w, int h)
419 {
420    EobjMoveResize(eo, EobjGetX(eo), EobjGetY(eo), w, h);
421 }
422
423 void
424 EobjDamage(EObj * eo)
425 {
426 #if USE_COMPOSITE
427    if (eo->cmhook)
428       ECompMgrWinDamageArea(eo, 0, 0, 0, 0);
429 #else
430    eo = NULL;
431 #endif
432 }
433
434 void
435 EobjReparent(EObj * eo, EObj * dst, int x, int y)
436 {
437    int                 move;
438
439    move = x != EobjGetX(eo) || y != EobjGetY(eo);
440
441    EReparentWindow(EobjGetWin(eo), EobjGetWin(dst), x, y);
442    if (dst->type == EOBJ_TYPE_DESK)
443      {
444         Desk               *dsk = (Desk *) dst;
445
446         if (eo->stacked < 0)
447           {
448              eo->desk = NULL;
449              eo->stacked = 0;
450           }
451         if (eo->desk != dsk)
452            DeskSetDirtyStack(dsk, eo);
453 #if USE_COMPOSITE
454         if (eo->cmhook)
455            ECompMgrWinReparent(eo, dsk, move);
456 #endif
457         eo->desk = dsk;
458      }
459    else
460      {
461         EobjListStackDel(eo);
462 #if USE_COMPOSITE
463         if (eo->cmhook)
464            ECompMgrWinDel(eo);
465 #endif
466      }
467 }
468
469 int
470 EobjRaise(EObj * eo)
471 {
472 #if USE_COMPOSITE
473    int                 num;
474
475    num = EobjListStackRaise(eo, 1);
476    if (num == 0)
477       return num;
478
479    if (num < 0)
480       num = EobjListStackRaise(eo, 0);
481    if (eo->shown && eo->cmhook)
482       ECompMgrWinRaiseLower(eo, num);
483    if (num > 0)
484       num = EobjListStackRaise(eo, 0);
485
486    return num;
487 #else
488    return EobjListStackRaise(eo, 0);
489 #endif
490 }
491
492 int
493 EobjLower(EObj * eo)
494 {
495 #if USE_COMPOSITE
496    int                 num;
497
498    num = EobjListStackLower(eo, 1);
499    if (num == 0)
500       return num;
501
502    if (num < 0)
503       num = EobjListStackLower(eo, 0);
504    if (eo->shown && eo->cmhook)
505       ECompMgrWinRaiseLower(eo, num);
506    if (num > 0)
507       num = EobjListStackLower(eo, 0);
508
509    return num;
510 #else
511    return EobjListStackLower(eo, 0);
512 #endif
513 }
514
515 void
516 EobjShapeUpdate(EObj * eo, int propagate)
517 {
518 #if USE_COMPOSITE
519    int                 was_shaped = eo->shaped;
520 #endif
521
522    if (propagate)
523       eo->shaped = EShapePropagate(EobjGetWin(eo)) != 0;
524    else
525       eo->shaped = EShapeCheck(EobjGetWin(eo)) != 0;
526
527 #if USE_COMPOSITE
528    if (was_shaped <= 0 && eo->shaped <= 0)
529       return;
530
531    /* Shape may still be unchanged. Well ... */
532    if (eo->shown && eo->cmhook)
533       ECompMgrWinChangeShape(eo);
534 #endif
535 }
536
537 Pixmap
538 EobjGetPixmap(const EObj * eo)
539 {
540    Pixmap              pmap = None;
541
542 #if USE_COMPOSITE
543    pmap = ECompMgrWinGetPixmap(eo);
544 #else
545    eo = NULL;
546 #endif
547    return pmap;
548 }
549
550 void
551 EobjChangeOpacity(EObj * eo, unsigned int opacity)
552 {
553 #if USE_COMPOSITE
554    if (eo->opacity == opacity)
555       return;
556    eo->opacity = opacity;
557    ECompMgrWinChangeOpacity(eo, opacity);
558 #else
559    eo = NULL;
560    opacity = 0;
561 #endif
562 }
563
564 #if USE_COMPOSITE
565 void
566 EobjChangeShadow(EObj * eo, int shadow)
567 {
568    ECompMgrWinChangeShadow(eo, shadow);
569 }
570 #endif
571
572 void
573 EobjSlideTo(EObj * eo, int fx, int fy, int tx, int ty, int speed)
574 {
575    int                 k, x, y;
576
577    EGrabServer();
578
579    ETimedLoopInit(0, 1024, speed);
580    for (k = 0; k <= 1024;)
581      {
582         x = ((fx * (1024 - k)) + (tx * k)) >> 10;
583         y = ((fy * (1024 - k)) + (ty * k)) >> 10;
584         EobjMove(eo, x, y);
585
586         k = ETimedLoopNext();
587      }
588    EobjMove(eo, tx, ty);
589
590    EUngrabServer();
591 }
592
593 void
594 EobjsSlideBy(EObj ** peo, int num, int dx, int dy, int speed)
595 {
596    int                 i, k, x, y;
597    struct _xy {
598       int                 x, y;
599    }                  *xy;
600
601    if (num <= 0)
602       return;
603
604    xy = EMALLOC(struct _xy, num);
605    if (!xy)
606       return;
607
608    for (i = 0; i < num; i++)
609      {
610         xy[i].x = EobjGetX(peo[i]);
611         xy[i].y = EobjGetY(peo[i]);
612      }
613
614    ETimedLoopInit(0, 1024, speed);
615    for (k = 0; k <= 1024;)
616      {
617         for (i = 0; i < num; i++)
618           {
619              x = ((xy[i].x * (1024 - k)) + ((xy[i].x + dx) * k)) >> 10;
620              y = ((xy[i].y * (1024 - k)) + ((xy[i].y + dy) * k)) >> 10;
621              EobjMove(peo[i], x, y);
622           }
623
624         k = ETimedLoopNext();
625      }
626
627    for (i = 0; i < num; i++)
628       EobjMove(peo[i], xy[i].x + dx, xy[i].y + dy);
629
630    Efree(xy);
631 }
632
633 void
634 EobjSlideSizeTo(EObj * eo, int fx, int fy, int tx, int ty, int fw, int fh,
635                 int tw, int th, int speed)
636 {
637    int                 k, x, y, w, h;
638
639    ETimedLoopInit(0, 1024, speed);
640    for (k = 0; k <= 1024;)
641      {
642         x = ((fx * (1024 - k)) + (tx * k)) >> 10;
643         y = ((fy * (1024 - k)) + (ty * k)) >> 10;
644         w = ((fw * (1024 - k)) + (tw * k)) >> 10;
645         h = ((fh * (1024 - k)) + (th * k)) >> 10;
646         EobjMoveResize(eo, x, y, w, h);
647
648         k = ETimedLoopNext();
649      }
650    EobjMoveResize(eo, tx, ty, tw, th);
651 }
652
653 void
654 EobjsRepaint(void)
655 {
656 #if USE_COMPOSITE
657    if (ECompMgrIsActive())
658       ECompMgrRepaint();
659    else
660 #endif
661       ESync(0);
662 }
663
664 #if USE_COMPOSITE
665 void
666 EobjsOpacityUpdate(int op_or)
667 {
668    EObj               *eo, *const *lst;
669    int                 i, num;
670
671    lst = EobjListStackGet(&num);
672    for (i = 0; i < num; i++)
673      {
674         eo = lst[i];
675         switch (eo->type)
676           {
677           default:
678              break;
679           case EOBJ_TYPE_EWIN:
680              EwinUpdateOpacity((EWin *) eo);
681              break;
682           case EOBJ_TYPE_EXT:
683              EobjChangeOpacity(eo, OpacityFromPercent(op_or));
684              break;
685           }
686      }
687 }
688 #endif