chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / src / slideout.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2004-2008 Kim Woelders
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies of the Software, its documentation and marketing & publicity
14  * materials, and acknowledgment shall be given in the documentation, materials
15  * and software packages that this Software was used.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include "E.h"
25 #include "aclass.h"
26 #include "borders.h"
27 #include "buttons.h"
28 #include "cursors.h"
29 #include "desktops.h"
30 #include "e16-ecore_list.h"
31 #include "emodule.h"
32 #include "eobj.h"
33 #include "ewins.h"
34 #include "grabs.h"
35 #include "xwin.h"
36
37 #define SLIDEOUT_EVENT_MASK \
38   (KeyPressMask | KeyReleaseMask | \
39    ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | \
40    PointerMotionMask)
41
42 typedef struct {
43    EObj                o;
44    char               *name;
45    char                direction;
46    int                 num_objs;
47    EObj              **objs;
48    unsigned int        ref_count;
49    EWin               *context_ewin;
50 } Slideout;
51
52 static void         SlideoutCalcSize(Slideout * s);
53
54 static Ecore_List  *slideout_list = NULL;
55
56 static struct {
57    Slideout           *active;
58 } Mode_slideouts =
59 {
60 NULL};
61
62 static void         SlideoutHandleEvent(Win win, XEvent * ev, void *prm);
63
64 static Slideout    *
65 SlideoutCreate(const char *name, char dir)
66 {
67    Slideout           *s;
68
69    s = ECALLOC(Slideout, 1);
70    if (!s)
71       return NULL;
72
73    s->name = Estrdup(name);
74    s->direction = dir;
75
76    EoInit(s, EOBJ_TYPE_MISC, None, -10, -10, 1, 1, 1, name);
77    EoSetShadow(s, 1);
78    ESelectInput(EoGetWin(s), SLIDEOUT_EVENT_MASK);
79    EventCallbackRegister(EoGetWin(s), 0, SlideoutHandleEvent, s);
80
81    return s;
82 }
83
84 static void
85 SlideoutShow(Slideout * s, EWin * ewin, Win win)
86 {
87    int                 x, y, i, xx, yy, sw, sh;
88    char                pdir;
89    XSetWindowAttributes att;
90    int                 w, h;
91    Desk               *dsk;
92
93    /* Don't ever show more than one slideout */
94    if (Mode_slideouts.active)
95       return;
96
97    SlideoutCalcSize(s);
98    EGetGeometry(win, NULL, NULL, NULL, &w, &h, NULL, NULL);
99    ETranslateCoordinates(win, VROOT, 0, 0, &x, &y, NULL);
100
101    sw = EoGetW(s);
102    sh = EoGetH(s);
103    xx = 0;
104    yy = 0;
105    switch (s->direction)
106      {
107      case 2:
108         xx = x + ((w - sw) >> 1);
109         yy = y - sh;
110         if ((yy < 0) && (sh < WinGetH(VROOT)))
111           {
112              pdir = s->direction;
113              s->direction = 1;
114              SlideoutShow(s, ewin, win);
115              s->direction = pdir;
116              return;
117           }
118         break;
119      case 3:
120         xx = x + ((w - sw) >> 1);
121         yy = y + h;
122         if (((yy + sh) > WinGetH(VROOT)) && (sh < WinGetH(VROOT)))
123           {
124              pdir = s->direction;
125              s->direction = 0;
126              SlideoutShow(s, ewin, win);
127              s->direction = pdir;
128              return;
129           }
130         break;
131      case 0:
132         xx = x - sw;
133         yy = y + ((h - sh) >> 1);
134         if ((xx < 0) && (sw < WinGetW(VROOT)))
135           {
136              pdir = s->direction;
137              s->direction = 1;
138              SlideoutShow(s, ewin, win);
139              s->direction = pdir;
140              return;
141           }
142         break;
143      case 1:
144         xx = x + w;
145         yy = y + ((h - sh) >> 1);
146         if (((xx + sw) > WinGetW(VROOT)) && (sw < WinGetW(VROOT)))
147           {
148              pdir = s->direction;
149              s->direction = 0;
150              SlideoutShow(s, ewin, win);
151              s->direction = pdir;
152              return;
153           }
154         break;
155      default:
156         break;
157      }
158
159    if (ewin)
160      {
161         /* If the slideout is associated with an ewin,
162          * put it on the same virtual desktop. */
163         dsk = EoGetDesk(ewin);
164         if (BorderWinpartIndex(ewin, win) >= 0 &&
165             !EoIsFloating(ewin) /* && !ewin->sticky */ )
166           {
167              xx -= EoGetX(dsk);
168              yy -= EoGetY(dsk);
169           }
170         EoSetLayer(s, EoGetLayer(ewin));
171      }
172    else
173      {
174         dsk = DeskGet(0);
175         EoSetLayer(s, 10);
176         EoSetFloating(s, 1);
177      }
178    EoReparent(s, EoObj(dsk), xx, yy);
179
180    switch (s->direction)
181      {
182      case 0:
183         att.win_gravity = SouthEastGravity;
184         EChangeWindowAttributes(EoGetWin(s), CWWinGravity, &att);
185         att.win_gravity = NorthWestGravity;
186         for (i = 0; i < s->num_objs; i++)
187            EChangeWindowAttributes(EobjGetWin(s->objs[i]), CWWinGravity, &att);
188         EoMoveResize(s, xx, yy, 1, 1);
189         ESync(ESYNC_SLIDEOUT);
190         EoMap(s, 2);
191         EobjSlideSizeTo(EoObj(s), xx + sw, yy, xx, yy, 1, sh, sw, sh,
192                         Conf.place.slidespeedmap);
193         break;
194      case 1:
195         att.win_gravity = NorthWestGravity;
196         EChangeWindowAttributes(EoGetWin(s), CWWinGravity, &att);
197         att.win_gravity = SouthEastGravity;
198         for (i = 0; i < s->num_objs; i++)
199            EChangeWindowAttributes(EobjGetWin(s->objs[i]), CWWinGravity, &att);
200         EoMoveResize(s, xx, yy, 1, 1);
201         ESync(ESYNC_SLIDEOUT);
202         EoMap(s, 2);
203         EobjSlideSizeTo(EoObj(s), xx, yy, xx, yy, 1, sh, sw, sh,
204                         Conf.place.slidespeedmap);
205         break;
206      case 2:
207         att.win_gravity = SouthEastGravity;
208         EChangeWindowAttributes(EoGetWin(s), CWWinGravity, &att);
209         att.win_gravity = NorthWestGravity;
210         for (i = 0; i < s->num_objs; i++)
211            EChangeWindowAttributes(EobjGetWin(s->objs[i]), CWWinGravity, &att);
212         EoMoveResize(s, xx, yy, 1, 1);
213         ESync(ESYNC_SLIDEOUT);
214         EoMap(s, 2);
215         EobjSlideSizeTo(EoObj(s), xx, yy + sh, xx, yy, sw, 1, sw, sh,
216                         Conf.place.slidespeedmap);
217         break;
218      case 3:
219         att.win_gravity = NorthWestGravity;
220         EChangeWindowAttributes(EoGetWin(s), CWWinGravity, &att);
221         att.win_gravity = SouthEastGravity;
222         for (i = 0; i < s->num_objs; i++)
223            EChangeWindowAttributes(EobjGetWin(s->objs[i]), CWWinGravity, &att);
224         EoMoveResize(s, xx, yy, 1, 1);
225         ESync(ESYNC_SLIDEOUT);
226         EoMap(s, 2);
227         EobjSlideSizeTo(EoObj(s), xx, yy, xx, yy, sw, 1, sw, sh,
228                         Conf.place.slidespeedmap);
229         break;
230      default:
231         break;
232      }
233    s->ref_count++;
234    s->context_ewin = ewin;
235
236    GrabPointerSet(EoGetWin(s), ECSR_ROOT, 0);
237
238    Mode_slideouts.active = s;
239 }
240
241 static void
242 SlideoutHide(Slideout * s)
243 {
244    if (!s)
245       return;
246
247    GrabPointerRelease();
248    EoUnmap(s);
249    s->context_ewin = NULL;
250    s->ref_count--;
251    Mode_slideouts.active = NULL;
252 }
253
254 static void
255 SlideoutCalcSize(Slideout * s)
256 {
257    int                 i, x, y;
258    int                 sw, sh, bw, bh;
259
260    if (!s)
261       return;
262
263    sw = 0;
264    sh = 0;
265    x = 0;
266    y = 0;
267    for (i = 0; i < s->num_objs; i++)
268      {
269         bw = EobjGetW(s->objs[i]);
270         bh = EobjGetH(s->objs[i]);
271
272         switch (s->direction)
273           {
274           case 2:
275           case 3:
276              if (bw > sw)
277                 sw = bw;
278              sh += bh;
279              break;
280           case 0:
281           case 1:
282              if (bh > sh)
283                 sh = bh;
284              sw += bw;
285              break;
286           default:
287              break;
288           }
289      }
290
291    EoResize(s, sw, sh);
292
293    for (i = 0; i < s->num_objs; i++)
294      {
295         bw = EobjGetW(s->objs[i]);
296         bh = EobjGetH(s->objs[i]);
297
298         switch (s->direction)
299           {
300           case 2:
301              y += bh;
302              EMoveWindow(EobjGetWin(s->objs[i]), (sw - bw) >> 1, sh - y);
303              break;
304           case 3:
305              EMoveWindow(EobjGetWin(s->objs[i]), (sw - bw) >> 1, y);
306              y += bh;
307              break;
308           case 0:
309              x += bw;
310              EMoveWindow(EobjGetWin(s->objs[i]), sw - x, (sh - bh) >> 1);
311              break;
312           case 1:
313              EMoveWindow(EobjGetWin(s->objs[i]), x, (sh - bh) >> 1);
314              x += bw;
315           default:
316              break;
317           }
318      }
319    EShapePropagate(EoGetWin(s));
320 }
321
322 static void
323 SlideoutButtonCallback(EObj * seo, XEvent * ev, ActionClass * ac)
324 {
325    Slideout           *s = (Slideout *) seo;
326    EWin               *ewin = s->context_ewin;
327
328    if (ev->type == ButtonRelease)
329       SlideoutHide(s);
330
331    if (ac)
332       ActionclassEvent(ac, ev, ewin);
333 }
334
335 static void
336 SlideoutAddButton(Slideout * s, Button * b)
337 {
338    EObj               *eob = (EObj *) b;
339
340    if (!s || !b)
341       return;
342
343    s->num_objs++;
344    s->objs = EREALLOC(EObj *, s->objs, s->num_objs);
345    s->objs[s->num_objs - 1] = eob;
346    ButtonSwallowInto(b, EoObj(s));
347    ButtonSetCallback(b, SlideoutButtonCallback, EoObj(s));
348    SlideoutCalcSize(s);
349 }
350
351 #if 0
352 static void
353 SlideoutRemoveButton(Slideout * s, Button * b)
354 {
355    s = NULL;
356    b = NULL;
357 }
358 #endif
359
360 static void
361 SlideoutHandleEvent(Win win __UNUSED__, XEvent * ev, void *prm)
362 {
363    Slideout           *s = (Slideout *) prm;
364
365    switch (ev->type)
366      {
367      case KeyPress:
368      case KeyRelease:
369         SlideoutHide(s);
370         break;
371      case ButtonPress:
372         break;
373      case ButtonRelease:
374         SlideoutHide(s);
375         break;
376      case EnterNotify:
377         if (ev->xcrossing.mode != NotifyGrab)
378            GrabPointerRelease();
379         break;
380      case LeaveNotify:
381         if (ev->xcrossing.mode != NotifyUngrab)
382            GrabPointerSet(EoGetWin(s), ECSR_ROOT, 0);
383         break;
384      }
385 }
386
387 static void
388 SlideoutsHide(void)
389 {
390    if (Mode_slideouts.active)
391       SlideoutHide(Mode_slideouts.active);
392 }
393
394 /*
395  * Configuration load/save
396  */
397 #include "conf.h"
398
399 int
400 SlideoutsConfigLoad(FILE * fs)
401 {
402    int                 err = 0;
403    Slideout           *slideout = 0;
404    int                 i1;
405    char                s[FILEPATH_LEN_MAX];
406    char                s2[FILEPATH_LEN_MAX];
407    char                name[FILEPATH_LEN_MAX];
408
409    if (!slideout_list)
410       slideout_list = ecore_list_new();
411
412    name[0] = '\0';
413
414    while (GetLine(s, sizeof(s), fs))
415      {
416         i1 = ConfigParseline1(s, s2, NULL, NULL);
417         switch (i1)
418           {
419           case CONFIG_CLOSE:
420              if (slideout)
421                 ecore_list_prepend(slideout_list, slideout);
422              goto done;
423           case CONFIG_CLASSNAME:
424              strcpy(name, s2);
425              break;
426           case SLIDEOUT_DIRECTION:
427              slideout = SlideoutCreate(name, (char)atoi(s2));
428              break;
429           case CONFIG_BUTTON:
430              SlideoutAddButton(slideout, ButtonFind(s2));
431              break;
432           default:
433              ConfigParseError("Slideout", s);
434              break;
435           }
436      }
437    err = -1;
438
439  done:
440    return err;
441 }
442
443 /*
444  * Slideouts Module
445  */
446
447 static void
448 SlideoutsSighan(int sig, void *prm)
449 {
450    switch (sig)
451      {
452      case ESIGNAL_AREA_SWITCH_START:
453      case ESIGNAL_DESK_SWITCH_START:
454         SlideoutsHide();
455         break;
456
457      case ESIGNAL_EWIN_UNMAP:
458         if (Mode_slideouts.active
459             && Mode_slideouts.active->context_ewin == (EWin *) prm)
460            SlideoutsHide();
461         break;
462      }
463 }
464
465 static int
466 _SlideoutMatchName(const void *data, const void *match)
467 {
468    return strcmp(((const Slideout *)data)->name, (const char *)match);
469 }
470
471 static Slideout    *
472 SlideoutFind(const char *name)
473 {
474    return (Slideout *) ecore_list_find(slideout_list, _SlideoutMatchName, name);
475 }
476
477 static void
478 IPC_Slideout(const char *params)
479 {
480    Slideout           *s;
481
482    if (!params)
483       return;
484
485    s = SlideoutFind(params);
486    if (!s)
487       return;
488
489    SoundPlay(SOUND_SLIDEOUT_SHOW);
490    SlideoutShow(s, GetContextEwin(), Mode.context_win);
491 }
492
493 static const IpcItem SlideoutsIpcArray[] = {
494    {
495     IPC_Slideout, "slideout", NULL, "Show slideout", NULL},
496 };
497 #define N_IPC_FUNCS (sizeof(SlideoutsIpcArray)/sizeof(IpcItem))
498
499 /*
500  * Module descriptor
501  */
502 extern const EModule ModSlideouts;
503 const EModule       ModSlideouts = {
504    "slideouts", "slideout",
505    SlideoutsSighan,
506    {N_IPC_FUNCS, SlideoutsIpcArray},
507    {0, NULL}
508 };