chiark / gitweb /
Imported Debian patch 1.0.0-5
[e16] / src / pager.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2004-2009 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 "backgrounds.h"
26 #include "desktops.h"
27 #include "dialog.h"
28 #include "e16-ecore_list.h"
29 #include "ecompmgr.h"
30 #include "emodule.h"
31 #include "ewins.h"
32 #include "focus.h"
33 #include "groups.h"
34 #include "hints.h"
35 #include "hiwin.h"
36 #include "iclass.h"
37 #include "menus.h"
38 #include "settings.h"
39 #include "timers.h"
40 #include "tooltips.h"
41 #include "xwin.h"
42
43 #define DEBUG_PAGER 0
44 #if DEBUG_PAGER
45 #define Dprintf(fmt...) if(EDebug(EDBUG_TYPE_PAGER))Eprintf(fmt)
46 #else
47 #define Dprintf(fmt...)
48 #endif
49
50 #define USE_PAGER_BACKGROUND_CACHE 1
51 #define HIQ ((Conf_pagers.hiq) ? 0x200 : 0x100)
52
53 #define PAGER_MODE_SIMPLE 0
54 #define PAGER_MODE_SNAP   1
55 #define PAGER_MODE_LIVE   2
56
57 #define PAGER_UPD_EWIN_GEOM     0
58 #define PAGER_UPD_EWIN_GONE     1
59 #define PAGER_UPD_EWIN_DAMAGE   2
60
61 #define EwinGetVX(ew) (ew->vx)
62 #define EwinGetVY(ew) (ew->vy)
63 #define EwinGetVX2(ew) (ew->vx + EoGetW(ew))
64 #define EwinGetVY2(ew) (ew->vy + EoGetH(ew))
65
66 static struct {
67    char                enable;
68    char                zoom;
69    char                title;
70    char                hiq;
71    int                 mode;
72    int                 scanspeed;
73    int                 sel_button;
74    int                 win_button;
75    int                 menu_button;
76 } Conf_pagers;
77
78 static struct {
79    int                 zoom;
80    Idler              *idler;
81    char                update_pending;
82    char                timer_pending;
83 } Mode_pagers;
84
85 typedef struct {
86    EWin               *ewin;
87    Win                 win;
88    int                 w, h;
89    char               *name;
90    Pixmap              bgpmap;
91    Desk               *dsk;
92    int                 dw, dh;
93    int                 screen_w, screen_h;
94    int                 update_phase;
95    Win                 sel_win;
96    Timer              *scan_timer;
97
98    /* State flags */
99    char                do_newbg;
100    char                do_update;
101    int                 x1, y1, x2, y2;
102    float               scale;
103    unsigned int        serial;
104    int                 serdif;
105 } Pager;
106
107 static void         PagerScanCancel(Pager * p);
108 static int          PagerScanTimeout(void *data);
109 static void         PagerCheckUpdate(Pager * p, void *prm);
110 static void         PagerUpdateEwinsFromPager(Pager * p);
111 static void         PagerHiwinHide(void);
112 static void         PagerEvent(Win win, XEvent * ev, void *prm);
113 static void         PagerHiwinEvent(Win win, XEvent * ev, void *prm);
114
115 static Ecore_List  *pager_list = NULL;
116
117 static Hiwin       *hiwin = NULL;
118
119 static int
120 PagersGetMode(void)
121 {
122    int                 mode = Conf_pagers.mode;
123
124    if (mode == PAGER_MODE_LIVE && !ECompMgrIsActive())
125       mode = PAGER_MODE_SNAP;
126
127    return mode;
128 }
129
130 static Pager       *
131 PagerCreate(void)
132 {
133    Pager              *p;
134
135    if (!Conf_pagers.enable)
136       return NULL;
137
138    p = ECALLOC(Pager, 1);
139    if (!p)
140       return NULL;
141
142    if (!pager_list)
143       pager_list = ecore_list_new();
144    ecore_list_append(pager_list, p);
145
146    p->name = NULL;
147    p->win = ECreateClientWindow(VROOT, 0, 0, 1, 1);
148    EventCallbackRegister(p->win, 0, PagerEvent, p);
149    p->sel_win = ECreateWindow(p->win, 0, 0, 1, 1, 0);
150
151    return p;
152 }
153
154 static void
155 PagerDestroy(Pager * p)
156 {
157    ecore_list_node_remove(pager_list, p);
158
159    PagerScanCancel(p);
160    Efree(p->name);
161    PagerHiwinHide();
162    if (p->bgpmap != None)
163       EFreePixmap(p->bgpmap);
164
165    Efree(p);
166 }
167
168 static void
169 PagerScanTrig(Pager * p)
170 {
171    if (p->scan_timer || Conf_pagers.scanspeed <= 0)
172       return;
173
174    TIMER_ADD(p->scan_timer, 1 / ((double)Conf_pagers.scanspeed),
175              PagerScanTimeout, p);
176 }
177
178 static void
179 PagerScanCancel(Pager * p)
180 {
181    TIMER_DEL(p->scan_timer);
182 }
183
184 static int
185 PagerScanTimeout(void *data)
186 {
187    Pager              *p;
188    EWin               *ewin;
189    int                 y, y2, phase, cx, cy, ww, hh, xx, yy;
190    static int          offsets[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
191    int                 pager_mode = PagersGetMode();
192
193    p = (Pager *) data;
194
195    if (pager_mode != PAGER_MODE_SNAP)
196       goto nomore;
197
198    ewin = p->ewin;
199    if (!ewin || !EoIsShown(ewin))
200       goto nomore;
201    if (p->dsk != DesksGetCurrent())
202       goto nomore;
203    if (ewin->state.visibility == VisibilityFullyObscured)
204       goto nomore;
205
206    if (Conf_pagers.scanspeed <= 0)
207       goto nomore;
208
209    if (Mode.mode != MODE_NONE)
210       goto nomore;
211
212    DeskCurrentGetArea(&cx, &cy);
213    ww = p->dw;
214    hh = p->dh;
215    xx = cx * ww;
216    yy = cy * hh;
217    phase = p->update_phase;
218    if (ww <= 0 || hh <= 0)
219       goto nomore;
220
221 #if 0
222    /* Due to a bug in imlib2 <= 1.2.0 we have to scan left->right in stead
223     * of top->bottom, at least for now. */
224    y = ((phase & 0xfffffff8) + offsets[phase % 8]) % hh;
225    y2 = (y * WinGetH(VROOT)) / hh;
226
227    ScaleRect(VROOT, WinGetXwin(VROOT), p->win, WinGetPmap(p->win), 0,
228              y2, WinGetW(VROOT), WinGetH(VROOT) / hh, xx, yy + y, ww, 1, HIQ);
229    EClearArea(p->win, xx, yy + y, ww, 1);
230    y2 = p->h;
231 #else
232    y = ((phase & 0xfffffff8) + offsets[phase % 8]) % ww;
233    y2 = (y * WinGetW(VROOT)) / ww;
234
235    ScaleRect(VROOT, WinGetXwin(VROOT), p->win, WinGetPmap(p->win), y2,
236              0, WinGetW(VROOT) / ww, WinGetH(VROOT), xx + y, yy, 1, hh, HIQ);
237    EClearArea(p->win, xx + y, yy, 1, hh);
238    y2 = p->w;
239 #endif
240    p->update_phase++;
241    if (p->update_phase >= y2)
242      {
243         PagerUpdateEwinsFromPager(p);
244         p->update_phase = 0;
245      }
246
247    TimerSetInterval(p->scan_timer, 1 / ((double)Conf_pagers.scanspeed));
248    return 1;
249
250  nomore:
251    p->scan_timer = NULL;
252    return 0;
253 }
254
255 #if 0                           /* FIXME - Remove? */
256 static void
257 PagerHiwinUpdate(Hiwin * phi, Pager * p __UNUSED__, EWin * ewin)
258 {
259    EImage             *im;
260
261    if (!EoIsShown(phi) || !ewin->mini_pmm.pmap)
262       return;
263
264    im = EImageGrabDrawable(ewin->mini_pmm.pmap, None, 0, 0,
265                            ewin->mini_w, ewin->mini_h, 0);
266    EImageRenderOnDrawable(im, EoGetWin(phi), 0, 0, 0, EoGetW(phi), EoGetH(phi));
267    EImageDecache(im);
268 }
269 #endif
270
271 static void
272 PagerEwinUpdateMini(Pager * p, EWin * ewin)
273 {
274    int                 w, h, update, use_iclass, serdif;
275    Drawable            draw;
276    int                 pager_mode = PagersGetMode();
277
278    w = (EoGetW(ewin) * p->dw) / WinGetW(VROOT);
279    h = (EoGetH(ewin) * p->dh) / WinGetH(VROOT);
280
281    if (w < 1)
282       w = 1;
283    if (h < 1)
284       h = 1;
285
286    serdif = EoGetSerial(ewin) - p->serial;
287
288    update = 0;
289    if (!ewin->mini_pmm.pmap)
290       update = 1;
291    if (ewin->mini_w != w || ewin->mini_h != h)
292       update = 1;
293
294    if (serdif > 0 && ewin->type != EWIN_TYPE_PAGER &&
295        pager_mode == PAGER_MODE_LIVE && Mode.mode == 0)
296       update = 1;
297    if (serdif > p->serdif)
298       p->serdif = serdif;
299
300    if (!update)
301       return;
302
303    Dprintf("PagerEwinUpdateMini %#lx/%#lx wxh=%dx%d ser=%#x/%#x dif=%d: %s\n",
304            EwinGetClientXwin(ewin), EoGetXwin(ewin), w, h,
305            EoGetSerial(ewin), p->serial, serdif, EwinGetTitle(ewin));
306
307    p->do_update = 1;
308
309    FreePmapMask(&ewin->mini_pmm);
310
311    ewin->mini_w = w;
312    ewin->mini_h = h;
313    ewin->mini_pmm.type = 0;
314    ewin->mini_pmm.pmap = ECreatePixmap(p->win, w, h, 0);
315
316    draw = None;
317    if (pager_mode != PAGER_MODE_SIMPLE)
318      {
319         draw = EoGetPixmap(ewin);
320         if (draw == None && EwinIsOnScreen(ewin))
321            draw = EoGetXwin(ewin);
322      }
323    use_iclass = draw == None;
324
325    if (use_iclass)
326      {
327         ImageClass         *ic;
328
329         ic = ImageclassFind("PAGER_WIN", 1);
330         ImageclassApplySimple(ic, p->win, ewin->mini_pmm.pmap,
331                               STATE_NORMAL, 0, 0, w, h);
332         Dprintf("Use Iclass, pmap=%#lx\n", ewin->mini_pmm.pmap);
333      }
334    else
335      {
336         ScaleRect(EoGetWin(ewin), draw, p->win, ewin->mini_pmm.pmap,
337                   0, 0, EoGetW(ewin), EoGetH(ewin), 0, 0, w, h, HIQ);
338         Dprintf("Grab scaled, pmap=%#lx\n", ewin->mini_pmm.pmap);
339      }
340
341 #if 0                           /* FIXME - Remove? */
342    if (hiwin && ewin == hiwin->ewin)
343       PagerHiwinUpdate(hiwin, p, ewin);
344 #endif
345 }
346
347 static void
348 doPagerUpdate(Pager * p)
349 {
350    int                 x, y, ax, ay, cx, cy, vx, vy;
351    GC                  gc = None;
352    EWin               *const *lst;
353    int                 i, num, update_screen_included, update_screen_only;
354    int                 pager_mode = PagersGetMode();
355    Pixmap              pmap;
356
357    p->update_phase = 0;
358    DesksGetAreaSize(&ax, &ay);
359    DeskGetArea(p->dsk, &cx, &cy);
360    vx = cx * WinGetW(VROOT);
361    vy = cy * WinGetH(VROOT);
362
363    update_screen_included = update_screen_only = 0;
364    if (pager_mode == PAGER_MODE_SNAP && p->dsk == DesksGetCurrent()
365        && Mode.mode == 0)
366      {
367         /* Update from screen unless update area is entirely off-screen */
368         if (!(p->x2 <= vx || p->y2 <= vy ||
369               p->x1 >= vx + WinGetW(VROOT) || p->y1 >= vy + WinGetH(VROOT)))
370            update_screen_included = 1;
371
372         /* Check if update area is entirely on-screen */
373         if (p->x1 >= vx && p->y1 >= vy &&
374             p->x2 <= vx + WinGetW(VROOT) && p->y2 <= vy + WinGetH(VROOT))
375            update_screen_only = 1;
376      }
377    p->x1 = p->y1 = 99999;
378    p->x2 = p->y2 = -99999;
379
380    pmap = EGetWindowBackgroundPixmap(p->win);
381
382    if (update_screen_only)
383       goto do_screen_update;
384
385    lst = EwinListGetForDesk(&num, p->dsk);
386    for (i = num - 1; i >= 0; i--)
387      {
388         EWin               *ewin;
389
390         ewin = lst[i];
391         if (!EoIsShown(ewin))
392            continue;
393
394         PagerEwinUpdateMini(p, ewin);
395      }
396    if (p->serdif > 0)
397       p->serial += p->serdif;
398    p->serdif = 0;
399
400    if (!p->do_update)
401       return;
402    p->do_update = 0;
403
404    gc = EXCreateGC(pmap, 0, NULL);
405    if (gc == None)
406       return;
407
408    Dprintf("doPagerUpdate %d: Repaint\n", p->dsk->num);
409    for (y = 0; y < ay; y++)
410      {
411         for (x = 0; x < ax; x++)
412           {
413 #if 0                           /* Skip? */
414              if (update_screen_included && x == cx && y == cy)
415                 continue;
416 #endif
417              XCopyArea(disp, p->bgpmap, pmap, gc, 0, 0, p->dw, p->dh,
418                        x * p->dw, y * p->dh);
419           }
420      }
421
422    for (i = num - 1; i >= 0; i--)
423      {
424         EWin               *ewin;
425         int                 wx, wy, ww, wh;
426
427         ewin = lst[i];
428         if (!EoIsShown(ewin))
429            continue;
430
431         wx = (EwinGetVX(ewin) * p->dw) / WinGetW(VROOT);
432         wy = (EwinGetVY(ewin) * p->dh) / WinGetH(VROOT);
433         ww = (EoGetW(ewin) * p->dw) / WinGetW(VROOT);
434         wh = (EoGetH(ewin) * p->dh) / WinGetH(VROOT);
435
436         if (ewin->mini_pmm.pmap)
437           {
438              if (ewin->mini_pmm.mask)
439                {
440                   XSetClipMask(disp, gc, ewin->mini_pmm.mask);
441                   XSetClipOrigin(disp, gc, wx, wy);
442                }
443              XCopyArea(disp, ewin->mini_pmm.pmap, pmap, gc, 0, 0,
444                        ww, wh, wx, wy);
445              if (ewin->mini_pmm.mask)
446                 XSetClipMask(disp, gc, None);
447           }
448         else
449           {
450              XSetForeground(disp, gc, Dpy.pixel_black);
451              XDrawRectangle(disp, pmap, gc, wx - 1, wy - 1, ww + 1, wh + 1);
452              XSetForeground(disp, gc, Dpy.pixel_white);
453              XFillRectangle(disp, pmap, gc, wx, wy, ww, wh);
454           }
455      }
456
457    if (!update_screen_included)
458      {
459         EClearWindow(p->win);
460         goto done;
461      }
462
463  do_screen_update:
464    Dprintf("doPagerUpdate %d: Snap screen\n", p->dsk->num);
465    /* Update pager area by snapshotting entire screen */
466    ScaleRect(VROOT, WinGetXwin(VROOT), p->win, pmap, 0, 0,
467              WinGetW(VROOT), WinGetH(VROOT), cx * p->dw, cy * p->dh,
468              p->dw, p->dh, HIQ);
469
470    EClearWindow(p->win);
471
472    /* Update ewin snapshots */
473    PagerUpdateEwinsFromPager(p);
474
475  done:
476    if (gc != None)
477       EXFreeGC(gc);
478 }
479
480 static void
481 PagerUpdate(Pager * p, int why, int x1, int y1, int x2, int y2)
482 {
483    if (!Conf_pagers.enable)
484       return;
485
486    if (p->x1 > x1)
487       p->x1 = x1;
488    if (p->y1 > y1)
489       p->y1 = y1;
490    if (p->x2 < x2)
491       p->x2 = x2;
492    if (p->y2 < y2)
493       p->y2 = y2;
494
495    p->do_update = 1;
496    Mode_pagers.update_pending |= 1 << why;
497 }
498
499 static void
500 PagerReconfigure(Pager * p, int apply)
501 {
502    int                 ax, ay, w, h, dx, dy;
503    double              aspect, f;
504
505    DesksGetAreaSize(&ax, &ay);
506
507    aspect = ((double)WinGetW(VROOT)) / ((double)WinGetH(VROOT));
508
509    dx = 2;
510    for (;;)
511      {
512         f = dx / aspect;
513         dy = (int)(f + .5);
514         f -= (double)dy;
515         if (f < 0)
516            f = -f;
517         if (f < .1)
518            break;
519         if (dx >= 8)
520            break;
521         dx += 1;
522      }
523
524    ICCCM_SetSizeConstraints(p->ewin,
525                             WinGetW(VROOT) / 64 * ax,
526                             WinGetH(VROOT) / 64 * ay,
527                             WinGetW(VROOT) / 4 * ax,
528                             WinGetH(VROOT) / 4 * ay, 0, 0, dx * ax, dy * ay,
529                             aspect * ((double)ax / (double)ay),
530                             aspect * ((double)ax / (double)ay));
531
532    if (apply)
533      {
534         w = (int)((double)ax * (double)WinGetW(VROOT) / (double)p->scale + .5);
535         h = (int)((double)ay * (double)WinGetH(VROOT) / (double)p->scale + .5);
536         EwinResize(p->ewin, w + (dx * ax) / 2, h + (dy * ay) / 2);
537         EwinReposition(p->ewin);
538      }
539 }
540
541 static void
542 PagerUpdateBg(Pager * p)
543 {
544    Pixmap              pmap;
545    GC                  gc;
546    Background         *bg;
547    ImageClass         *ic;
548    int                 pager_mode = PagersGetMode();
549
550    p->x1 = p->y1 = 0;
551    p->x2 = p->y2 = 99999;
552
553    pmap = p->bgpmap;
554    if (pmap != None)
555       EFreePixmap(pmap);
556    pmap = p->bgpmap = ECreatePixmap(p->win, p->dw, p->dh, 0);
557
558    bg = DeskBackgroundGet(p->dsk);
559    if (pager_mode != PAGER_MODE_SIMPLE && bg)
560      {
561 #if USE_PAGER_BACKGROUND_CACHE
562         char                s[4096];
563         char               *uniq;
564         EImage             *im;
565
566         uniq = BackgroundGetUniqueString(bg);
567         Esnprintf(s, sizeof(s), "%s/cached/pager/%s.%i.%i.%s.png",
568                   EDirUserCache(), BackgroundGetName(bg), p->dw, p->dh, uniq);
569         Efree(uniq);
570
571         im = EImageLoad(s);
572         if (im)
573           {
574              EImageRenderOnDrawable(im, p->win, pmap, 0, 0, 0, p->dw, p->dh);
575              EImageDecache(im);
576           }
577         else
578           {
579 #endif
580              BackgroundApplyPmap(bg, p->win, pmap, p->dw, p->dh);
581 #if USE_PAGER_BACKGROUND_CACHE
582              im = EImageGrabDrawable(pmap, None, 0, 0, p->dw, p->dh, 0);
583              EImageSave(im, s);
584              EImageDecache(im);
585           }
586 #endif
587         return;
588      }
589
590    if (pager_mode != PAGER_MODE_SIMPLE && p->dsk->bg.pmap)
591      {
592         ScaleTile(VROOT, p->dsk->bg.pmap, p->win, pmap,
593                   0, 0, p->dw, p->dh, HIQ);
594         return;
595      }
596
597    ic = ImageclassFind("PAGER_BACKGROUND", 1);
598    if (ic)
599      {
600         ImageclassApplySimple(ic, p->win, pmap, STATE_NORMAL,
601                               0, 0, p->dw, p->dh);
602         return;
603      }
604
605    gc = EXCreateGC(pmap, 0, NULL);
606    if (gc == None)
607       return;
608
609    XSetForeground(disp, gc, Dpy.pixel_black);
610    XDrawRectangle(disp, pmap, gc, 0, 0, p->dw, p->dh);
611    XSetForeground(disp, gc, Dpy.pixel_white);
612    XFillRectangle(disp, pmap, gc, 1, 1, p->dw - 2, p->dh - 2);
613
614    EXFreeGC(gc);
615 }
616
617 static void
618 _PagerEwinInit(EWin * ewin)
619 {
620    Pager              *p = (Pager *) ewin->data;
621    char                s[128];
622
623    Esnprintf(s, sizeof(s), "Pager-%i", p->dsk->num);
624    EwinSetTitle(ewin, s);
625    Esnprintf(s, sizeof(s), "%i", p->dsk->num);
626    EwinSetClass(ewin, s, "Enlightenment_Pager");
627
628    ewin->props.skip_ext_task = 1;
629    ewin->props.skip_ext_pager = 1;
630    ewin->props.skip_focuslist = 1;
631    ewin->props.skip_winlist = 1;
632    EwinInhSetWM(ewin, focus, 1);
633    ewin->props.autosave = 1;
634
635    EoSetSticky(ewin, 1);
636 }
637
638 static void
639 _PagerEwinMoveResize(EWin * ewin, int resize __UNUSED__)
640 {
641    Pager              *p = (Pager *) ewin->data;
642    int                 w, h;
643    int                 ax, ay, cx, cy;
644    ImageClass         *ic;
645
646    if (!Conf_pagers.enable || !p || Mode.mode != MODE_NONE)
647       return;
648
649    w = ewin->client.w;
650    h = ewin->client.h;
651    if ((w == p->w && h == p->h) || w <= 1 || h <= 1)
652       return;
653
654    DesksGetAreaSize(&ax, &ay);
655
656    p->w = w;
657    p->h = h;
658    p->dw = w / ax;
659    p->dh = h / ay;
660
661    if (p->scale <= 0. || Mode.op_source == OPSRC_USER)
662       p->scale = ((float)WinGetW(VROOT) / p->dw +
663                   (float)WinGetH(VROOT) / p->dh) / 2;
664
665    p->do_newbg = 1;
666    PagerCheckUpdate(p, NULL);
667
668    ic = ImageclassFind("PAGER_SEL", 0);
669    if (ic)
670      {
671         DeskGetArea(p->dsk, &cx, &cy);
672         EMoveResizeWindow(p->sel_win, cx * p->dw, cy * p->dh, p->dw, p->dh);
673         ImageclassApply(ic, p->sel_win, 0, 0, STATE_NORMAL, ST_PAGER);
674      }
675 }
676
677 static void
678 _PagerEwinClose(EWin * ewin)
679 {
680    PagerDestroy((Pager *) ewin->data);
681    ewin->data = NULL;
682 }
683
684 static const EWinOps _PagerEwinOps = {
685    _PagerEwinInit,
686    NULL,
687    _PagerEwinMoveResize,
688    _PagerEwinClose,
689 };
690
691 static void
692 PagerShow(Pager * p)
693 {
694    EWin               *ewin;
695    int                 w, h;
696
697    if (!Conf_pagers.enable)
698       return;
699
700    if (p->ewin)
701      {
702         EwinShow(p->ewin);
703         return;
704      }
705
706    ewin = AddInternalToFamily(p->win, "PAGER", EWIN_TYPE_PAGER,
707                               &_PagerEwinOps, p);
708    p->ewin = ewin;
709    if (!ewin)
710       return;
711
712    p->screen_w = WinGetW(VROOT);
713    p->screen_h = WinGetH(VROOT);
714
715    PagerReconfigure(p, 0);
716
717    ewin->client.event_mask |=
718       ButtonPressMask | ButtonReleaseMask |
719       EnterWindowMask | LeaveWindowMask | PointerMotionMask;
720    ESelectInput(p->win, ewin->client.event_mask);
721
722    w = ewin->client.w;
723    h = ewin->client.h;
724
725    EwinMoveToDesktop(ewin, EoGetDesk(ewin));
726    if (ewin->state.placed)
727      {
728         EwinMoveResize(ewin, EoGetX(ewin), EoGetY(ewin), w, h);
729      }
730    else
731      {
732         /* no snapshots ? first time ? make a row on the bottom left up */
733         int                 ax, ay;
734
735         DesksGetAreaSize(&ax, &ay);
736         w = ((48 * WinGetW(VROOT)) / WinGetH(VROOT)) * ax;
737         h = 48 * ay;
738         EwinResize(ewin, w, h); /* Does layout */
739         EwinMove(ewin, 0, WinGetH(VROOT) -
740                  (DesksGetNumber() - p->dsk->num) * EoGetH(ewin));
741      }
742
743    EwinShow(ewin);
744 }
745
746 typedef struct {
747    Desk               *dsk;
748    void                (*func) (Pager * p, void *prm);
749    void               *prm;
750 } pager_foreach_data;
751
752 static void
753 _PagersForeachFunc(void *item, void *prm)
754 {
755    Pager              *p = (Pager *) item;
756    pager_foreach_data *data = (pager_foreach_data *) prm;
757
758    if (data->dsk && data->dsk != p->dsk)
759       return;
760    data->func(p, data->prm);
761 }
762
763 static void
764 PagersForeach(Desk * dsk, void (*func) (Pager * p, void *prm), void *prm)
765 {
766    pager_foreach_data  data;
767
768    data.dsk = dsk;
769    data.func = func;
770    data.prm = prm;
771    ecore_list_for_each(pager_list, _PagersForeachFunc, &data);
772 }
773
774 typedef struct {
775    int                 why;
776    int                 x1, y1, x2, y2;
777 } pager_update_data;
778
779 static void
780 _PagerUpdate(Pager * p, void *prm)
781 {
782    pager_update_data  *pud = (pager_update_data *) prm;
783
784    PagerUpdate(p, pud->why, pud->x1, pud->y1, pud->x2, pud->y2);
785 }
786
787 static void
788 PagersUpdate(Desk * dsk, int why, int x1, int y1, int x2, int y2)
789 {
790    pager_update_data   pud;
791
792    if (ecore_list_count(pager_list) <= 0)
793       return;
794
795    pud.why = why;
796    pud.x1 = x1;
797    pud.y1 = y1;
798    pud.x2 = x2;
799    pud.y2 = y2;
800    PagersForeach(dsk, _PagerUpdate, &pud);
801 }
802
803 static void
804 PagerCheckUpdate(Pager * p, void *prm __UNUSED__)
805 {
806    if (p->do_newbg)
807      {
808         PagerUpdateBg(p);
809         p->do_update = 1;
810      }
811
812    if (p->do_update)
813       doPagerUpdate(p);
814
815    p->do_newbg = p->do_update = 0;
816 }
817
818 static int
819 _PagersUpdateTimeout(void *data __UNUSED__)
820 {
821    Mode_pagers.timer_pending = 0;
822
823    return 0;
824 }
825
826 static void
827 PagersCheckUpdate(void)
828 {
829    static double       tlast = 0.;
830    double              t, dt;
831    Timer              *pager_update_timer;
832
833    if (!Mode_pagers.update_pending || !Conf_pagers.enable)
834       return;
835
836    if (Mode_pagers.update_pending == (1 << PAGER_UPD_EWIN_DAMAGE))
837      {
838         t = GetTime();
839         dt = (Conf_pagers.scanspeed > 0) ? 1. / Conf_pagers.scanspeed : .1;
840         if (t - tlast < dt)
841           {
842              /* The purpose of this timer is to trigger the idler */
843              if (!Mode_pagers.timer_pending)
844                 TIMER_ADD(pager_update_timer, dt, _PagersUpdateTimeout, NULL);
845              Mode_pagers.timer_pending = 1;
846              return;
847           }
848         tlast = t;
849      }
850
851    PagersForeach(NULL, PagerCheckUpdate, NULL);
852
853    Mode_pagers.update_pending = 0;
854 }
855
856 static void
857 _PagersIdler(void *data __UNUSED__)
858 {
859    PagersCheckUpdate();
860 }
861
862 static void
863 PagerEwinUpdateFromPager(Pager * p, EWin * ewin)
864 {
865    int                 x, y, w, h;
866    static GC           gc = 0;
867
868    if (!EoIsShown(ewin) || !EwinIsOnScreen(ewin))
869       return;
870
871    Dprintf("PagerEwinUpdateFromPager %d\n", p->dsk->num);
872
873    x = EwinGetVX(ewin);
874    y = EwinGetVY(ewin);
875    w = EoGetW(ewin);
876    h = EoGetH(ewin);
877    x = (x * p->dw) / WinGetW(VROOT);
878    y = (y * p->dh) / WinGetH(VROOT);
879    w = (w * p->dw) / WinGetW(VROOT);
880    h = (h * p->dh) / WinGetH(VROOT);
881    if (w <= 0)
882       w = 1;
883    if (h <= 0)
884       h = 1;
885
886    if (!gc)
887       gc = EXCreateGC(WinGetPmap(p->win), 0, NULL);
888
889    /* NB! If the pixmap/mask was created by imlib, free it. Due to imlibs */
890    /*     image/pixmap cache it may be in use elsewhere. */
891    if (ewin->mini_pmm.pmap &&
892        ((ewin->mini_pmm.type) || (ewin->mini_w != w) || (ewin->mini_h != h)))
893       FreePmapMask(&ewin->mini_pmm);
894
895    if (!ewin->mini_pmm.pmap)
896      {
897         ewin->mini_w = w;
898         ewin->mini_h = h;
899         ewin->mini_pmm.type = 0;
900         ewin->mini_pmm.pmap = ECreatePixmap(p->win, w, h, 0);
901         ewin->mini_pmm.mask = None;
902      }
903
904    if (!ewin->mini_pmm.pmap)
905       return;
906
907    XCopyArea(disp, WinGetPmap(p->win), ewin->mini_pmm.pmap, gc, x, y, w, h, 0,
908              0);
909
910 #if 0                           /* FIXME - Remove? */
911    if (hiwin && ewin == hiwin->ewin)
912       PagerHiwinUpdate(hiwin, p, ewin);
913 #endif
914 }
915
916 static void
917 PagerUpdateEwinsFromPager(Pager * p)
918 {
919    int                 i, num;
920    EWin               *const *lst;
921
922    lst = EwinListGetForDesk(&num, p->dsk);
923    for (i = 0; i < num; i++)
924       PagerEwinUpdateFromPager(p, lst[i]);
925 }
926
927 static void
928 PagersUpdateEwin(EWin * ewin, int why)
929 {
930    Desk               *dsk;
931
932    if (!Conf_pagers.enable)
933       return;
934
935    switch (why)
936      {
937      case PAGER_UPD_EWIN_GEOM:
938         if (!EoIsShown(ewin) || ewin->state.animated)
939            return;
940         break;
941
942      case PAGER_UPD_EWIN_GONE:
943         if (ewin == HiwinGetEwin(hiwin, 0))
944            PagerHiwinHide();
945         break;
946
947      case PAGER_UPD_EWIN_DAMAGE:
948         if (ewin->type == EWIN_TYPE_PAGER)
949            return;
950         if (PagersGetMode() != PAGER_MODE_LIVE)
951            return;
952         break;
953      }
954
955    dsk = (EoIsFloating(ewin)) ? DesksGetCurrent() : EoGetDesk(ewin);
956    PagersUpdate(dsk, why, EwinGetVX(ewin), EwinGetVY(ewin),
957                 EwinGetVX2(ewin), EwinGetVY2(ewin));
958 }
959
960 static EWin        *
961 EwinInPagerAt(Pager * p, int px, int py)
962 {
963    EWin               *const *lst, *ewin;
964    int                 i, num, x, y, w, h;
965
966    if (!Conf_pagers.enable)
967       return NULL;
968
969    lst = EwinListGetForDesk(&num, p->dsk);
970    for (i = 0; i < num; i++)
971      {
972         ewin = lst[i];
973         if (!EoIsShown(ewin))
974            continue;
975
976         x = (EwinGetVX(ewin) * p->dw) / WinGetW(VROOT);
977         y = (EwinGetVY(ewin) * p->dh) / WinGetH(VROOT);
978         w = (EoGetW(ewin) * p->dw) / WinGetW(VROOT);
979         h = (EoGetH(ewin) * p->dh) / WinGetH(VROOT);
980
981         if (px >= x && py >= y && px < (x + w) && py < (y + h))
982            return ewin;
983      }
984
985    return NULL;
986 }
987
988 static void
989 PagerMenuShow(Pager * p, int x, int y)
990 {
991    static Menu        *p_menu = NULL, *pw_menu = NULL;
992    MenuItem           *mi;
993    EWin               *ewin;
994    char                s[1024];
995
996    if (!Conf_pagers.enable)
997       return;
998
999    ewin = EwinInPagerAt(p, x, y);
1000    if (ewin)
1001      {
1002         if (pw_menu)
1003            MenuDestroy(pw_menu);
1004
1005         pw_menu =
1006            MenuCreate("__DESK_WIN_MENU", _("Window Options"), NULL, NULL);
1007
1008         Esnprintf(s, sizeof(s), "wop %#lx ic", EwinGetClientXwin(ewin));
1009         mi = MenuItemCreate(_("Iconify"), NULL, s, NULL);
1010         MenuAddItem(pw_menu, mi);
1011
1012         Esnprintf(s, sizeof(s), "wop %#lx close", EwinGetClientXwin(ewin));
1013         mi = MenuItemCreate(_("Close"), NULL, s, NULL);
1014         MenuAddItem(pw_menu, mi);
1015
1016         Esnprintf(s, sizeof(s), "wop %#lx kill", EwinGetClientXwin(ewin));
1017         mi = MenuItemCreate(_("Annihilate"), NULL, s, NULL);
1018         MenuAddItem(pw_menu, mi);
1019
1020         Esnprintf(s, sizeof(s), "wop %#lx st", EwinGetClientXwin(ewin));
1021         mi = MenuItemCreate(_("Stick / Unstick"), NULL, s, NULL);
1022         MenuAddItem(pw_menu, mi);
1023
1024         EFunc(NULL, "menus show __DESK_WIN_MENU");
1025         return;
1026      }
1027
1028    if (p_menu)
1029       MenuDestroy(p_menu);
1030    p_menu = MenuCreate("__DESK_MENU", _("Desktop Options"), NULL, NULL);
1031
1032    mi = MenuItemCreate(_("Pager Settings..."), NULL, "cfg pagers", NULL);
1033    MenuAddItem(p_menu, mi);
1034
1035    if (PagersGetMode() != PAGER_MODE_SIMPLE)
1036      {
1037         mi = MenuItemCreate(_("Snapshotting Off"), NULL, "pg mode simp", NULL);
1038         MenuAddItem(p_menu, mi);
1039
1040         if (Conf_pagers.hiq)
1041            mi = MenuItemCreate(_("High Quality Off"), NULL, "pg hiq off", NULL);
1042         else
1043            mi = MenuItemCreate(_("High Quality On"), NULL, "pg hiq on", NULL);
1044         MenuAddItem(p_menu, mi);
1045      }
1046    else
1047      {
1048         mi = MenuItemCreate(_("Snapshotting On"), NULL, "pg mode live", NULL);
1049         MenuAddItem(p_menu, mi);
1050      }
1051    if (Conf_pagers.zoom)
1052       mi = MenuItemCreate(_("Zoom Off"), NULL, "pg zoom off", NULL);
1053    else
1054       mi = MenuItemCreate(_("Zoom On"), NULL, "pg zoom on", NULL);
1055    MenuAddItem(p_menu, mi);
1056
1057    EFunc(NULL, "menus show __DESK_MENU");
1058 }
1059
1060 static void
1061 PagerClose(Pager * p)
1062 {
1063    EwinHide(p->ewin);
1064 }
1065
1066 static void
1067 _PagerUpdateSel(Pager * p, void *prm __UNUSED__)
1068 {
1069    int                 cx, cy;
1070    ImageClass         *ic;
1071
1072    if (p->dsk != DesksGetCurrent())
1073       EUnmapWindow(p->sel_win);
1074    else
1075      {
1076         DeskGetArea(p->dsk, &cx, &cy);
1077         EMoveWindow(p->sel_win, cx * p->dw, cy * p->dh);
1078         EMapWindow(p->sel_win);
1079         ic = ImageclassFind("PAGER_SEL", 0);
1080         if (ic)
1081            ImageclassApply(ic, p->sel_win, 0, 0, STATE_NORMAL, ST_PAGER);
1082      }
1083 }
1084
1085 static void
1086 UpdatePagerSel(void)
1087 {
1088    if (!Conf_pagers.enable)
1089       return;
1090
1091    PagersForeach(NULL, _PagerUpdateSel, NULL);
1092 }
1093
1094 static void
1095 PagerShowTt(EWin * ewin)
1096 {
1097    static EWin        *tt_ewin = NULL;
1098    ToolTip            *tt;
1099
1100    Dprintf("PagerShowTt %s\n", (ewin) ? EwinGetIconName(ewin) : NULL);
1101
1102    if (!Conf_pagers.title || (ewin == tt_ewin))
1103       return;
1104
1105    if (MenusActive())           /* Don't show Tooltip when menu is up */
1106       return;
1107
1108    tt = TooltipFind("PAGER");
1109    if (tt)
1110      {
1111         if (ewin)
1112            TooltipShow(tt, EwinGetIconName(ewin), NULL, Mode.events.cx,
1113                        Mode.events.cy);
1114         else
1115            TooltipHide(tt);
1116      }
1117
1118    tt_ewin = ewin;
1119 }
1120
1121 static void
1122 PagerHiwinInit(Pager * p, EWin * ewin)
1123 {
1124    Hiwin              *phi = hiwin;
1125    int                 wx, wy, ww, wh, px, py;
1126
1127    if (!phi)
1128      {
1129         phi = HiwinCreate();
1130         if (!phi)
1131            return;
1132         hiwin = phi;
1133      }
1134
1135    wx = (EwinGetVX(ewin) * p->dw) / WinGetW(VROOT);
1136    wy = (EwinGetVY(ewin) * p->dh) / WinGetH(VROOT);
1137    ww = (EoGetW(ewin) * p->dw) / WinGetW(VROOT);
1138    wh = (EoGetH(ewin) * p->dh) / WinGetH(VROOT);
1139    ETranslateCoordinates(p->win, VROOT, 0, 0, &px, &py, NULL);
1140
1141    HiwinInit(phi, ewin);
1142    HiwinSetGeom(phi, px + wx, py + wy, ww, wh);
1143    HiwinSetCallback(phi, PagerHiwinEvent, p);
1144 }
1145
1146 static void
1147 PagerHiwinHide(void)
1148 {
1149    Dprintf("PagerHiwinHide\n");
1150    HiwinHide(hiwin);
1151    PagerShowTt(NULL);
1152 }
1153
1154 static void
1155 PagerHiwinShow(Pager * p, EWin * ewin, int zoom, int confine)
1156 {
1157    Hiwin              *phi = hiwin;
1158
1159    if (MenusActive())           /* Don't show HiWin when menu is up */
1160       return;
1161
1162    if (!phi || ewin)
1163      {
1164         PagerHiwinInit(p, ewin);
1165         phi = hiwin;
1166         if (!phi)
1167            return;
1168      }
1169
1170    HiwinShow(phi, ewin, zoom, confine);
1171 }
1172
1173 static void
1174 PagerZoomChange(Pager * p, int delta)
1175 {
1176    Dprintf("PagerZoomChange delta=%d\n", delta);
1177
1178    if (delta == 0)
1179       return;
1180
1181    if (delta > 0)
1182      {
1183         if (!ECompMgrIsActive() && Mode_pagers.zoom >= 2)
1184            return;
1185         if (Mode_pagers.zoom >= 8)
1186            return;
1187         Mode_pagers.zoom++;
1188      }
1189    else
1190      {
1191         if (Mode_pagers.zoom <= 2)
1192            return;
1193         Mode_pagers.zoom--;
1194      }
1195    PagerHiwinShow(p, NULL, Mode_pagers.zoom, 0);
1196 }
1197
1198 static void
1199 PagerHandleMotion(Pager * p, int x, int y)
1200 {
1201    EWin               *ewin;
1202    int                 on_screen;
1203
1204    if (!Conf_pagers.enable)
1205       return;
1206
1207    on_screen = EQueryPointer(p->win, &x, &y, NULL, NULL);
1208
1209    if (on_screen && x >= 0 && x < p->w && y >= 0 && y < p->h)
1210       ewin = EwinInPagerAt(p, x, y);
1211    else
1212       ewin = NULL;
1213
1214    if (!Conf_pagers.zoom)
1215      {
1216         PagerShowTt(ewin);
1217         return;
1218      }
1219
1220    if (!ewin || EoGetLayer(ewin) <= 0)
1221      {
1222         PagerHiwinHide();
1223      }
1224    else if (!hiwin || ewin != HiwinGetEwin(hiwin, 0))
1225      {
1226         if (Mode_pagers.zoom < 2)
1227            Mode_pagers.zoom = 2;
1228         PagerHiwinShow(p, ewin, Mode_pagers.zoom, 0);
1229      }
1230    if (Mode_pagers.zoom <= 2)
1231       PagerShowTt(ewin);
1232 }
1233
1234 static void
1235 NewPagerForDesktop(Desk * dsk)
1236 {
1237    Pager              *p;
1238
1239    p = PagerCreate();
1240    if (!p)
1241       return;
1242
1243    p->dsk = dsk;
1244    PagerShow(p);
1245 }
1246
1247 static void
1248 _PagerUpdateBackground(Pager * p, void *prm __UNUSED__)
1249 {
1250    p->do_newbg = 1;
1251 }
1252
1253 static void
1254 PagersUpdateBackground(Desk * dsk)
1255 {
1256    PagersForeach(dsk, _PagerUpdateBackground, NULL);
1257
1258    Mode_pagers.update_pending = 1;
1259 }
1260
1261 static void
1262 PagerSetHiQ(char onoff)
1263 {
1264    EWin               *const *lst;
1265    int                 i, num;
1266
1267    Conf_pagers.hiq = onoff;
1268
1269    lst = EwinListGetAll(&num);
1270    for (i = 0; i < num; i++)
1271      {
1272         lst[i]->mini_w = 0;
1273         lst[i]->mini_h = 0;
1274      }
1275
1276    PagersUpdateBackground(NULL);
1277
1278    autosave();
1279 }
1280
1281 static void
1282 _PagerSetSnap(Pager * p, void *prm __UNUSED__)
1283 {
1284    PagerScanTrig(p);
1285 }
1286
1287 static void
1288 PagersSetMode(int mode)
1289 {
1290    EWin               *const *lst;
1291    int                 i, num;
1292
1293    if (mode == Conf_pagers.mode)
1294       return;
1295    Conf_pagers.mode = mode;
1296
1297    lst = EwinListGetAll(&num);
1298    for (i = 0; i < num; i++)
1299      {
1300         lst[i]->mini_w = 0;
1301         lst[i]->mini_h = 0;
1302      }
1303
1304    PagersUpdateBackground(NULL);
1305
1306    if (Conf_pagers.mode == PAGER_MODE_SNAP && Conf_pagers.scanspeed > 0)
1307       PagersForeach(DesksGetCurrent(), _PagerSetSnap, NULL);
1308
1309    autosave();
1310 }
1311
1312 /*
1313  * Pager event handlers
1314  */
1315
1316 static int         *gwin_px, *gwin_py;
1317
1318 static void
1319 PagerEwinGroupSet(void)
1320 {
1321    int                 i, num;
1322    EWin               *ewin, **gwins;
1323
1324    ewin = HiwinGetEwin(hiwin, 0);
1325    gwins = ListWinGroupMembersForEwin(ewin, GROUP_ACTION_MOVE,
1326                                       Mode.nogroup, &num);
1327    if (!gwins)
1328       return;
1329
1330    gwin_px = EMALLOC(int, num);
1331    gwin_py = EMALLOC(int, num);
1332
1333    for (i = 0; i < num; i++)
1334      {
1335         gwin_px[i] = EoGetX(gwins[i]);
1336         gwin_py[i] = EoGetY(gwins[i]);
1337      }
1338
1339    Efree(gwins);
1340 }
1341
1342 static void
1343 PagerEwinGroupUnset(void)
1344 {
1345    _EFREE(gwin_px);
1346    _EFREE(gwin_py);
1347 }
1348
1349 static void
1350 PagerEventUnmap(Pager * p __UNUSED__)
1351 {
1352    PagerHiwinHide();
1353 }
1354
1355 static void
1356 EwinGroupMove(EWin * ewin, Desk * dsk, int x, int y)
1357 {
1358    int                 i, num, dx, dy, newdesk;
1359    EWin              **gwins;
1360
1361    if (!ewin)
1362       return;
1363
1364    /* Move all group members */
1365    newdesk = dsk != EoGetDesk(ewin);
1366    dx = x - EoGetX(ewin);
1367    dy = y - EoGetY(ewin);
1368    gwins =
1369       ListWinGroupMembersForEwin(ewin, GROUP_ACTION_MOVE, Mode.nogroup, &num);
1370    for (i = 0; i < num; i++)
1371      {
1372         if (gwins[i]->type == EWIN_TYPE_PAGER)
1373            continue;
1374
1375         if (newdesk)
1376            EwinOpMoveToDesktopAt(gwins[i], OPSRC_USER, dsk,
1377                                  EoGetX(gwins[i]) + dx, EoGetY(gwins[i]) + dy);
1378         else
1379            EwinOpMove(gwins[i], OPSRC_USER, EoGetX(gwins[i]) + dx,
1380                       EoGetY(gwins[i]) + dy);
1381      }
1382    Efree(gwins);
1383 }
1384
1385 static void
1386 PagerEwinMove(Pager * p __UNUSED__, Pager * pd, EWin * ewin)
1387 {
1388    int                 x, y, dx, dy, px, py;
1389    int                 cx, cy;
1390    Hiwin              *phi = hiwin;
1391
1392    /* Delta in pager coords */
1393    dx = Mode.events.mx - Mode.events.px;
1394    dy = Mode.events.my - Mode.events.py;
1395
1396    if (dx == 0 && dy == 0 && p == pd)
1397       return;
1398
1399    /* Move mini window */
1400    HiwinGetXY(phi, &x, &y);
1401    HiwinMove(phi, x + dx, y + dy);
1402
1403    /* Find real window position */
1404    ETranslateCoordinates(VROOT, pd->win, x, y, &px, &py, NULL);
1405    DeskGetArea(pd->dsk, &cx, &cy);
1406    x = (px * WinGetW(VROOT)) / pd->dw - cx * WinGetW(VROOT);
1407    y = (py * WinGetH(VROOT)) / pd->dh - cy * WinGetH(VROOT);
1408
1409    /* Move all group members */
1410    EwinGroupMove(ewin, pd->dsk, x, y);
1411 }
1412
1413 static void
1414 PagerHandleMouseDown(Pager * p, int px, int py, int button)
1415 {
1416    int                 in_pager;
1417    EWin               *ewin;
1418
1419    in_pager = (px >= 0 && py >= 0 && px < p->w && py < p->h);
1420    if (!in_pager)
1421       return;
1422
1423    if (button == Conf_pagers.menu_button)
1424      {
1425         PagerHiwinHide();
1426         PagerMenuShow(p, px, py);
1427      }
1428    else if (button == Conf_pagers.win_button)
1429      {
1430         ewin = EwinInPagerAt(p, px, py);
1431         if (ewin && ewin->type != EWIN_TYPE_PAGER && !ewin->state.inhibit_move)
1432           {
1433              PagerHiwinShow(p, ewin, 1, !Mode.wm.window);
1434              Mode.mode = MODE_PAGER_DRAG_PENDING;
1435              PagerEwinGroupSet();
1436           }
1437      }
1438 }
1439
1440 static void
1441 PagerHiwinHandleMouseDown(Pager * p, int px, int py, int button)
1442 {
1443    PagerHandleMouseDown(p, px, py, button);
1444 }
1445
1446 static void
1447 PagerHandleMouseUp(Pager * p, int px, int py, int button)
1448 {
1449    int                 in_pager;
1450    EWin               *ewin;
1451
1452    in_pager = (px >= 0 && py >= 0 && px < p->w && py < p->h);
1453    if (!in_pager)
1454       return;
1455
1456    if (button == Conf_pagers.sel_button)
1457      {
1458         DeskGoto(p->dsk);
1459         if (p->dsk != DesksGetCurrent())
1460            SoundPlay(SOUND_DESKTOP_SHUT);
1461         DeskCurrentGotoArea(px / p->dw, py / p->dh);
1462      }
1463    else if (button == Conf_pagers.win_button)
1464      {
1465         DeskGoto(p->dsk);
1466         DeskCurrentGotoArea(px / p->dw, py / p->dh);
1467         ewin = EwinInPagerAt(p, px, py);
1468         if (ewin)
1469           {
1470              EwinRaise(ewin);
1471              FocusToEWin(ewin, FOCUS_SET);
1472           }
1473      }
1474 }
1475
1476 static void
1477 PagerHiwinHandleMouseUp(Pager * p, int px, int py, int button)
1478 {
1479    int                 i, num, in_vroot;
1480    EWin               *ewin, *ewin2, **gwins;
1481    int                 x, y;
1482
1483    Dprintf("PagerHiwinHandleMouseUp m=%d d=%d x,y=%d,%d\n", Mode.mode,
1484            p->dsk->num, px, py);
1485
1486    if (Mode.mode != MODE_PAGER_DRAG)
1487      {
1488         if (Mode.mode == MODE_PAGER_DRAG_PENDING)
1489            Mode.mode = MODE_NONE;
1490         PagerHiwinHide();
1491         PagerHandleMouseUp(p, px, py, button);
1492         return;
1493      }
1494
1495    Mode.mode = MODE_NONE;
1496
1497    ewin = HiwinGetEwin(hiwin, 1);
1498    if (!ewin)
1499       goto done;
1500
1501    in_vroot = (Mode.events.cx >= 0 && Mode.events.cx < WinGetW(VROOT) &&
1502                Mode.events.cy >= 0 && Mode.events.cy < WinGetH(VROOT));
1503
1504    if (button == Conf_pagers.win_button)
1505      {
1506         /* Find which pager or iconbox we are in (if any) */
1507         ewin2 = GetEwinPointerInClient();
1508         if ((ewin2) && (ewin2->type == EWIN_TYPE_PAGER))
1509           {
1510              PagerEwinMove(p, (Pager *) ewin2->data, ewin);
1511           }
1512         else if ((ewin2) && (ewin2->type == EWIN_TYPE_ICONBOX))
1513           {
1514              /* Pointer is in iconbox */
1515
1516              /* Iconify after moving back to pre-drag position */
1517              gwins = ListWinGroupMembersForEwin(ewin, GROUP_ACTION_MOVE,
1518                                                 Mode.nogroup, &num);
1519              for (i = 0; i < num; i++)
1520                {
1521                   if (gwins[i]->type != EWIN_TYPE_PAGER)
1522                     {
1523                        EwinMove(gwins[i], gwin_px[i], gwin_py[i]);
1524                        EwinIconify(gwins[i]);
1525                     }
1526                }
1527              Efree(gwins);
1528           }
1529         else if (ewin2 && ewin2->props.vroot)
1530           {
1531              /* Dropping onto virtual root */
1532              EwinReparent(ewin, EwinGetClientWin(ewin2));
1533           }
1534         else if (!in_vroot)
1535           {
1536              /* Move back to real root */
1537              EwinReparent(ewin, RROOT);
1538           }
1539         else
1540           {
1541              /* Pointer is not in pager or iconbox */
1542              /* Move window(s) to pointer location */
1543              x = Mode.events.cx - EoGetW(ewin) / 2;
1544              y = Mode.events.cy - EoGetH(ewin) / 2;
1545              EwinGroupMove(ewin, DesksGetCurrent(), x, y);
1546           }
1547      }
1548
1549    PagerHiwinHide();
1550
1551  done:
1552    /* unallocate the space that was holding the old positions of the */
1553    /* windows */
1554    PagerEwinGroupUnset();
1555 }
1556
1557 static void
1558 PagerEvent(Win win __UNUSED__, XEvent * ev, void *prm)
1559 {
1560    Pager              *p = (Pager *) prm;
1561
1562    Dprintf("PagerEvent ev=%d\n", ev->type);
1563
1564    switch (ev->type)
1565      {
1566      case ButtonPress:
1567         PagerHandleMouseDown(p, ev->xbutton.x, ev->xbutton.y,
1568                              (int)ev->xbutton.button);
1569         break;
1570      case ButtonRelease:
1571         if (ev->xbutton.window != Mode.events.last_bpress)
1572            break;
1573         PagerHandleMouseUp(p, ev->xbutton.x, ev->xbutton.y,
1574                            (int)ev->xbutton.button);
1575         break;
1576
1577      case MotionNotify:
1578         PagerHandleMotion(p, ev->xmotion.x, ev->xmotion.y);
1579         break;
1580
1581      case EnterNotify:
1582         break;
1583      case LeaveNotify:
1584         PagerShowTt(NULL);
1585         break;
1586
1587      case UnmapNotify:
1588         PagerEventUnmap(p);
1589         break;
1590
1591      case VisibilityNotify:
1592         if (ev->xvisibility.state != VisibilityFullyObscured)
1593            PagerScanTrig(p);
1594         break;
1595      }
1596 }
1597
1598 static void
1599 PagerHiwinEvent(Win win, XEvent * ev, void *prm)
1600 {
1601    Pager              *p = (Pager *) prm;
1602    int                 px, py;
1603    EWin               *ewin;
1604
1605    if (!p)
1606       return;
1607
1608    Dprintf("PagerHiwinEvent ev=%d\n", ev->type);
1609
1610    switch (ev->type)
1611      {
1612      case ButtonPress:
1613         switch (ev->xbutton.button)
1614           {
1615           case 4:
1616              if (Mode.mode != MODE_NONE)
1617                 break;
1618              PagerZoomChange(p, 1);
1619              break;
1620           case 5:
1621              if (Mode.mode != MODE_NONE)
1622                 break;
1623              PagerZoomChange(p, -1);
1624              break;
1625           default:
1626              /* Translate x,y to pager window coordinates */
1627              ETranslateCoordinates(win, p->win,
1628                                    ev->xbutton.x, ev->xbutton.y, &px, &py,
1629                                    NULL);
1630              PagerHiwinHandleMouseDown(p, px, py, (int)ev->xbutton.button);
1631              break;
1632           }
1633         break;
1634
1635      case ButtonRelease:
1636         switch (ev->xbutton.button)
1637           {
1638           case 4:
1639           case 5:
1640              break;
1641           default:
1642              /* Translate x,y to pager window coordinates */
1643              ETranslateCoordinates(win, p->win,
1644                                    ev->xbutton.x, ev->xbutton.y, &px, &py,
1645                                    NULL);
1646              PagerHiwinHandleMouseUp(p, px, py, (int)ev->xbutton.button);
1647              break;
1648           }
1649         break;
1650
1651      case MotionNotify:
1652         switch (Mode.mode)
1653           {
1654           case MODE_NONE:
1655              PagerHandleMotion(p, ev->xmotion.x, ev->xmotion.y);
1656              break;
1657
1658           case MODE_PAGER_DRAG_PENDING:
1659           case MODE_PAGER_DRAG:
1660              ewin = HiwinGetEwin(hiwin, 1);
1661              if (!ewin || ewin->type == EWIN_TYPE_PAGER)
1662                {
1663                   Mode.mode = MODE_NONE;
1664                   break;
1665                }
1666
1667              Mode.mode = MODE_PAGER_DRAG;
1668              PagerEwinMove(p, p, ewin);
1669              break;
1670           }
1671         break;
1672
1673      case LeaveNotify:
1674         PagerShowTt(NULL);
1675         break;
1676      }
1677 }
1678
1679 /*
1680  * Pagers handling
1681  */
1682
1683 static int
1684 PagersForDesktopCount(Desk * dsk)
1685 {
1686    Pager              *p;
1687    int                 num = 0;
1688
1689    ECORE_LIST_FOR_EACH(pager_list, p)
1690    {
1691       if (p->dsk == dsk)
1692          num++;
1693    }
1694
1695    return num;
1696 }
1697
1698 static void
1699 _PagerClose(Pager * p, void *prm __UNUSED__)
1700 {
1701    PagerClose(p);
1702 }
1703
1704 static void
1705 PagersForDesktopEnable(Desk * dsk)
1706 {
1707    if (PagersForDesktopCount(dsk) <= 0)
1708       NewPagerForDesktop(dsk);
1709 }
1710
1711 static void
1712 PagersForDesktopDisable(Desk * dsk)
1713 {
1714    PagersForeach(dsk, _PagerClose, NULL);
1715 }
1716
1717 static void
1718 PagersShow(int enable)
1719 {
1720    unsigned int        i;
1721
1722    if (enable && !Conf_pagers.enable)
1723      {
1724         Conf_pagers.enable = 1;
1725         for (i = 0; i < DesksGetNumber(); i++)
1726            PagersForDesktopEnable(DeskGet(i));
1727         UpdatePagerSel();
1728         Mode_pagers.idler = IdlerAdd(_PagersIdler, NULL);
1729      }
1730    else if (!enable && Conf_pagers.enable)
1731      {
1732         for (i = 0; i < DesksGetNumber(); i++)
1733            PagersForDesktopDisable(DeskGet(i));
1734         Conf_pagers.enable = 0;
1735         IdlerDel(Mode_pagers.idler);
1736         Mode_pagers.idler = NULL;
1737      }
1738 }
1739
1740 static void
1741 _PagerReconfigure(Pager * p, void *prm __UNUSED__)
1742 {
1743    PagerReconfigure(p, 1);
1744 }
1745
1746 static int
1747 _PagersReconfigureTimeout(void *data __UNUSED__)
1748 {
1749    PagersForeach(NULL, _PagerReconfigure, NULL);
1750
1751    return 0;
1752 }
1753
1754 static void
1755 PagersReconfigure(void)
1756 {
1757    Timer              *pg_timer_cfg;
1758
1759    if (!Conf_pagers.enable)
1760       return;
1761
1762    TIMER_ADD(pg_timer_cfg, .5, _PagersReconfigureTimeout, NULL);
1763 }
1764
1765 #if ENABLE_DIALOGS
1766 /*
1767  * Configuration dialog
1768  */
1769 static char         tmp_show_pagers;
1770 static char         tmp_pager_hiq;
1771 static int          tmp_pager_mode;
1772 static char         tmp_pager_zoom;
1773 static char         tmp_pager_title;
1774 static char         tmp_pager_do_scan;
1775 static int          tmp_pager_scan_speed;
1776 static int          tmp_pager_sel_button;
1777 static int          tmp_pager_win_button;
1778 static int          tmp_pager_menu_button;
1779 static DItem       *pager_scan_speed_label = NULL;
1780
1781 static void
1782 CB_ConfigurePager(Dialog * d __UNUSED__, int val, void *data __UNUSED__)
1783 {
1784    if (val < 2)
1785      {
1786         PagersShow(tmp_show_pagers);
1787         if (Conf_pagers.hiq != tmp_pager_hiq)
1788            PagerSetHiQ(tmp_pager_hiq);
1789         Conf_pagers.zoom = tmp_pager_zoom;
1790         Conf_pagers.title = tmp_pager_title;
1791         Conf_pagers.sel_button = tmp_pager_sel_button;
1792         Conf_pagers.win_button = tmp_pager_win_button;
1793         Conf_pagers.menu_button = tmp_pager_menu_button;
1794         if ((Conf_pagers.scanspeed != tmp_pager_scan_speed)
1795             || ((!tmp_pager_do_scan) && (Conf_pagers.scanspeed > 0))
1796             || ((tmp_pager_do_scan) && (Conf_pagers.scanspeed == 0)))
1797           {
1798              if (tmp_pager_do_scan)
1799                 Conf_pagers.scanspeed = tmp_pager_scan_speed;
1800              else
1801                 Conf_pagers.scanspeed = 0;
1802           }
1803         PagersSetMode(tmp_pager_mode);
1804      }
1805    autosave();
1806 }
1807
1808 static void
1809 CB_PagerScanSlide(Dialog * d, int val __UNUSED__, void *data __UNUSED__)
1810 {
1811    char                s[256];
1812
1813    Esnprintf(s, sizeof(s), "%s %03i %s", _("Pager scanning speed:"),
1814              tmp_pager_scan_speed, _("lines per second"));
1815    DialogItemSetText(pager_scan_speed_label, s);
1816    DialogDrawItems(d, pager_scan_speed_label, 0, 0, 99999, 99999);
1817 }
1818
1819 static void
1820 _DlgFillPagers(Dialog * d __UNUSED__, DItem * table, void *data __UNUSED__)
1821 {
1822    DItem              *di, *radio;
1823    char                s[256];
1824
1825    tmp_show_pagers = Conf_pagers.enable;
1826    tmp_pager_hiq = Conf_pagers.hiq;
1827    tmp_pager_mode = Conf_pagers.mode;
1828    tmp_pager_zoom = Conf_pagers.zoom;
1829    tmp_pager_title = Conf_pagers.title;
1830    tmp_pager_sel_button = Conf_pagers.sel_button;
1831    tmp_pager_win_button = Conf_pagers.win_button;
1832    tmp_pager_menu_button = Conf_pagers.menu_button;
1833    if (Conf_pagers.scanspeed == 0)
1834       tmp_pager_do_scan = 0;
1835    else
1836       tmp_pager_do_scan = 1;
1837    tmp_pager_scan_speed = Conf_pagers.scanspeed;
1838
1839    DialogItemTableSetOptions(table, 2, 0, 0, 0);
1840
1841    di = DialogAddItem(table, DITEM_CHECKBUTTON);
1842    DialogItemSetColSpan(di, 2);
1843    DialogItemSetText(di, _("Enable pager display"));
1844    DialogItemCheckButtonSetPtr(di, &tmp_show_pagers);
1845
1846    di = DialogAddItem(table, DITEM_SEPARATOR);
1847    DialogItemSetColSpan(di, 2);
1848
1849    di = DialogAddItem(table, DITEM_TEXT);
1850    DialogItemSetColSpan(di, 2);
1851    DialogItemSetFill(di, 0, 0);
1852    DialogItemSetAlign(di, 0, 512);
1853    DialogItemSetText(di, _("Pager Mode:"));
1854
1855    radio = di = DialogAddItem(table, DITEM_RADIOBUTTON);
1856    DialogItemSetColSpan(di, 2);
1857    DialogItemSetText(di, _("Simple"));
1858    DialogItemRadioButtonSetFirst(di, radio);
1859    DialogItemRadioButtonGroupSetVal(di, 0);
1860
1861    di = DialogAddItem(table, DITEM_RADIOBUTTON);
1862    DialogItemSetColSpan(di, 2);
1863    DialogItemSetText(di, _("Make miniature snapshots of the screen"));
1864    DialogItemRadioButtonSetFirst(di, radio);
1865    DialogItemRadioButtonGroupSetVal(di, 1);
1866
1867 #if USE_COMPOSITE
1868    di = DialogAddItem(table, DITEM_RADIOBUTTON);
1869    DialogItemSetColSpan(di, 2);
1870    DialogItemSetText(di, _("Live Update"));
1871    DialogItemRadioButtonSetFirst(di, radio);
1872    DialogItemRadioButtonGroupSetVal(di, 2);
1873 #endif
1874    DialogItemRadioButtonGroupSetValPtr(radio, &tmp_pager_mode);
1875
1876    di = DialogAddItem(table, DITEM_SEPARATOR);
1877    DialogItemSetColSpan(di, 2);
1878
1879    di = DialogAddItem(table, DITEM_CHECKBUTTON);
1880    DialogItemSetColSpan(di, 2);
1881    DialogItemSetText(di, _("Smooth high quality snapshots in snapshot mode"));
1882    DialogItemCheckButtonSetPtr(di, &tmp_pager_hiq);
1883
1884    di = DialogAddItem(table, DITEM_CHECKBUTTON);
1885    DialogItemSetColSpan(di, 2);
1886    DialogItemSetText(di, _("Zoom in on pager windows when mouse is over them"));
1887    DialogItemCheckButtonSetPtr(di, &tmp_pager_zoom);
1888
1889    di = DialogAddItem(table, DITEM_CHECKBUTTON);
1890    DialogItemSetColSpan(di, 2);
1891    DialogItemSetText(di,
1892                      _("Pop up window title when mouse is over the window"));
1893    DialogItemCheckButtonSetPtr(di, &tmp_pager_title);
1894
1895    di = DialogAddItem(table, DITEM_CHECKBUTTON);
1896    DialogItemSetColSpan(di, 2);
1897    DialogItemSetText(di, _("Continuously scan screen to update pager"));
1898    DialogItemCheckButtonSetPtr(di, &tmp_pager_do_scan);
1899
1900    di = pager_scan_speed_label = DialogAddItem(table, DITEM_TEXT);
1901    DialogItemSetColSpan(di, 2);
1902    DialogItemSetFill(di, 0, 0);
1903    DialogItemSetAlign(di, 0, 512);
1904    Esnprintf(s, sizeof(s), "%s %03i %s", _("Pager scanning speed:"),
1905              tmp_pager_scan_speed, _("lines per second"));
1906    DialogItemSetText(di, s);
1907
1908    di = DialogAddItem(table, DITEM_SLIDER);
1909    DialogItemSliderSetBounds(di, 1, 256);
1910    DialogItemSliderSetUnits(di, 1);
1911    DialogItemSliderSetJump(di, 1);
1912    DialogItemSetColSpan(di, 2);
1913    DialogItemSliderSetValPtr(di, &tmp_pager_scan_speed);
1914    DialogItemSetCallback(di, CB_PagerScanSlide, 0, NULL);
1915
1916    di = DialogAddItem(table, DITEM_TEXT);
1917    DialogItemSetColSpan(di, 2);
1918    DialogItemSetFill(di, 0, 0);
1919    DialogItemSetAlign(di, 0, 512);
1920    DialogItemSetText(di, _("Mouse button to select and drag windows:"));
1921
1922    radio = di = DialogAddItem(table, DITEM_RADIOBUTTON);
1923    DialogItemSetColSpan(di, 2);
1924    DialogItemSetText(di, _("Left"));
1925    DialogItemRadioButtonSetFirst(di, radio);
1926    DialogItemRadioButtonGroupSetVal(di, 1);
1927
1928    di = DialogAddItem(table, DITEM_RADIOBUTTON);
1929    DialogItemSetColSpan(di, 2);
1930    DialogItemSetText(di, _("Middle"));
1931    DialogItemRadioButtonSetFirst(di, radio);
1932    DialogItemRadioButtonGroupSetVal(di, 2);
1933
1934    di = DialogAddItem(table, DITEM_RADIOBUTTON);
1935    DialogItemSetColSpan(di, 2);
1936    DialogItemSetText(di, _("Right"));
1937    DialogItemRadioButtonSetFirst(di, radio);
1938    DialogItemRadioButtonGroupSetVal(di, 3);
1939    DialogItemRadioButtonGroupSetValPtr(radio, &tmp_pager_win_button);
1940
1941    di = DialogAddItem(table, DITEM_TEXT);
1942    DialogItemSetColSpan(di, 2);
1943    DialogItemSetFill(di, 0, 0);
1944    DialogItemSetAlign(di, 0, 512);
1945    DialogItemSetText(di, _("Mouse button to select desktops:"));
1946
1947    radio = di = DialogAddItem(table, DITEM_RADIOBUTTON);
1948    DialogItemSetColSpan(di, 2);
1949    DialogItemSetText(di, _("Left"));
1950    DialogItemRadioButtonSetFirst(di, radio);
1951    DialogItemRadioButtonGroupSetVal(di, 1);
1952
1953    di = DialogAddItem(table, DITEM_RADIOBUTTON);
1954    DialogItemSetColSpan(di, 2);
1955    DialogItemSetText(di, _("Middle"));
1956    DialogItemRadioButtonSetFirst(di, radio);
1957    DialogItemRadioButtonGroupSetVal(di, 2);
1958
1959    di = DialogAddItem(table, DITEM_RADIOBUTTON);
1960    DialogItemSetColSpan(di, 2);
1961    DialogItemSetText(di, _("Right"));
1962    DialogItemRadioButtonSetFirst(di, radio);
1963    DialogItemRadioButtonGroupSetVal(di, 3);
1964    DialogItemRadioButtonGroupSetValPtr(radio, &tmp_pager_sel_button);
1965
1966    di = DialogAddItem(table, DITEM_TEXT);
1967    DialogItemSetColSpan(di, 2);
1968    DialogItemSetFill(di, 0, 0);
1969    DialogItemSetAlign(di, 0, 512);
1970    DialogItemSetText(di, _("Mouse button to display pager menu:"));
1971
1972    radio = di = DialogAddItem(table, DITEM_RADIOBUTTON);
1973    DialogItemSetColSpan(di, 2);
1974    DialogItemSetText(di, _("Left"));
1975    DialogItemRadioButtonSetFirst(di, radio);
1976    DialogItemRadioButtonGroupSetVal(di, 1);
1977
1978    di = DialogAddItem(table, DITEM_RADIOBUTTON);
1979    DialogItemSetColSpan(di, 2);
1980    DialogItemSetText(di, _("Middle"));
1981    DialogItemRadioButtonSetFirst(di, radio);
1982    DialogItemRadioButtonGroupSetVal(di, 2);
1983
1984    di = DialogAddItem(table, DITEM_RADIOBUTTON);
1985    DialogItemSetColSpan(di, 2);
1986    DialogItemSetText(di, _("Right"));
1987    DialogItemRadioButtonSetFirst(di, radio);
1988    DialogItemRadioButtonGroupSetVal(di, 3);
1989    DialogItemRadioButtonGroupSetValPtr(radio, &tmp_pager_menu_button);
1990 }
1991
1992 const DialogDef     DlgPagers = {
1993    "CONFIGURE_PAGER",
1994    N_("Pagers"),
1995    N_("Pager Settings"),
1996    SOUND_SETTINGS_PAGER,
1997    "pix/pager.png",
1998    N_("Enlightenment Desktop & Area\n" "Pager Settings Dialog\n"),
1999    _DlgFillPagers,
2000    DLG_OAC, CB_ConfigurePager,
2001 };
2002 #endif /* ENABLE_DIALOGS */
2003
2004 /*
2005  * Pagers Module
2006  */
2007
2008 static void
2009 PagersSighan(int sig, void *prm)
2010 {
2011    switch (sig)
2012      {
2013      case ESIGNAL_INIT:
2014         memset(&Mode_pagers, 0, sizeof(Mode_pagers));
2015         EDirMake(EDirUserCache(), "cached/pager");
2016         break;
2017      case ESIGNAL_CONFIGURE:
2018         break;
2019      case ESIGNAL_START:
2020         if (!Conf_pagers.enable)
2021            break;
2022         Conf_pagers.enable = 0;
2023         PagersShow(1);
2024         break;
2025
2026      case ESIGNAL_AREA_CONFIGURED:
2027         PagersReconfigure();
2028         break;
2029      case ESIGNAL_AREA_SWITCH_START:
2030         PagerHiwinHide();
2031         break;
2032      case ESIGNAL_AREA_SWITCH_DONE:
2033         PagersUpdate(DesksGetCurrent(), PAGER_UPD_EWIN_GEOM,
2034                      0, 0, 99999, 99999);
2035         UpdatePagerSel();
2036         break;
2037
2038      case ESIGNAL_DESK_ADDED:
2039         if (Mode.wm.startup)
2040            break;
2041         NewPagerForDesktop((Desk *) prm);
2042         break;
2043      case ESIGNAL_DESK_REMOVED:
2044         PagersForDesktopDisable((Desk *) prm);
2045         break;
2046      case ESIGNAL_DESK_SWITCH_START:
2047         PagerHiwinHide();
2048         break;
2049      case ESIGNAL_DESK_SWITCH_DONE:
2050         UpdatePagerSel();
2051         break;
2052      case ESIGNAL_DESK_RESIZE:
2053         PagersReconfigure();
2054         break;
2055
2056      case ESIGNAL_BACKGROUND_CHANGE:
2057         PagersUpdateBackground((Desk *) prm);
2058         break;
2059
2060      case ESIGNAL_EWIN_UNMAP:
2061         PagersUpdateEwin((EWin *) prm, PAGER_UPD_EWIN_GONE);
2062         break;
2063      case ESIGNAL_EWIN_CHANGE:
2064         PagersUpdateEwin((EWin *) prm, PAGER_UPD_EWIN_GEOM);
2065         break;
2066      case ESIGNAL_EWIN_DAMAGE:
2067         PagersUpdateEwin((EWin *) prm, PAGER_UPD_EWIN_DAMAGE);
2068         break;
2069      }
2070 }
2071
2072 static void
2073 IPC_Pager(const char *params)
2074 {
2075    const char         *p = params;
2076    char                prm1[128];
2077    int                 len, desk;
2078    Desk               *dsk;
2079
2080    if (!p)
2081       return;
2082
2083    prm1[0] = '\0';
2084    len = 0;
2085    sscanf(p, "%100s %n", prm1, &len);
2086    p += len;
2087
2088    if (!strcmp(prm1, "on"))
2089      {
2090         PagersShow(1);
2091      }
2092    else if (!strcmp(prm1, "off"))
2093      {
2094         PagersShow(0);
2095      }
2096    else if (!strcmp(prm1, "desk"))
2097      {
2098         desk = -1;
2099         prm1[0] = '\0';
2100         sscanf(p, "%d %100s", &desk, prm1);
2101         dsk = DeskGet(desk);
2102
2103         if (!dsk)
2104           {
2105              ;
2106           }
2107         else if (!strcmp(prm1, "on"))
2108           {
2109              PagersForDesktopEnable(dsk);
2110           }
2111         else if (!strcmp(prm1, "new"))
2112           {
2113              NewPagerForDesktop(dsk);
2114           }
2115         else if (!strcmp(prm1, "off"))
2116           {
2117              PagersForDesktopDisable(dsk);
2118           }
2119      }
2120    else if (!strcmp(prm1, "hiq"))
2121      {
2122         if (!strcmp(p, "on"))
2123            PagerSetHiQ(1);
2124         else if (!strcmp(p, "off"))
2125            PagerSetHiQ(0);
2126      }
2127    else if (!strcmp(prm1, "mode"))
2128      {
2129         if (!strncmp(p, "si", 2))
2130            PagersSetMode(PAGER_MODE_SIMPLE);
2131         else if (!strncmp(p, "sn", 2))
2132            PagersSetMode(PAGER_MODE_SNAP);
2133         else if (!strncmp(p, "li", 2))
2134            PagersSetMode(PAGER_MODE_LIVE);
2135      }
2136    else if (!strcmp(prm1, "zoom"))
2137      {
2138         if (!strcmp(p, "on"))
2139            Conf_pagers.zoom = 1;
2140         else if (!strcmp(p, "off"))
2141            Conf_pagers.zoom = 0;
2142      }
2143 }
2144
2145 static const IpcItem PagersIpcArray[] = {
2146    {
2147     IPC_Pager,
2148     "pager", "pg",
2149     "Toggle the status of the Pager and various pager settings",
2150     "use \"pager <on/off>\" to set the current mode\nuse \"pager ?\" "
2151     "to get the current mode\n"
2152     "  pager <#> <on/off/?>   Toggle or test any desktop's pager\n"
2153     "  pager hiq <on/off>     Toggle high quality pager\n"
2154     "  pager scanrate <#>     Toggle number of line updates per second\n"
2155     "  pager mode <mode>      Set pager mode (simple/snapshot/live)\n"
2156     "  pager title <on/off>   Toggle title display in the pager\n"
2157     "  pager zoom <on/off>    Toggle zooming in the pager\n"}
2158    ,
2159 };
2160 #define N_IPC_FUNCS (sizeof(PagersIpcArray)/sizeof(IpcItem))
2161
2162 /*
2163  * Configuration items
2164  */
2165 static const CfgItem PagersCfgItems[] = {
2166    CFG_ITEM_BOOL(Conf_pagers, enable, 1),
2167    CFG_ITEM_BOOL(Conf_pagers, zoom, 1),
2168    CFG_ITEM_BOOL(Conf_pagers, title, 1),
2169    CFG_ITEM_BOOL(Conf_pagers, hiq, 1),
2170    CFG_ITEM_INT(Conf_pagers, mode, PAGER_MODE_LIVE),
2171    CFG_ITEM_INT(Conf_pagers, scanspeed, 10),
2172    CFG_ITEM_INT(Conf_pagers, sel_button, 2),
2173    CFG_ITEM_INT(Conf_pagers, win_button, 1),
2174    CFG_ITEM_INT(Conf_pagers, menu_button, 3),
2175 };
2176 #define N_CFG_ITEMS (sizeof(PagersCfgItems)/sizeof(CfgItem))
2177
2178 /*
2179  * Module descriptor
2180  */
2181 extern const EModule ModPagers;
2182 const EModule       ModPagers = {
2183    "pagers", "pg",
2184    PagersSighan,
2185    {N_IPC_FUNCS, PagersIpcArray},
2186    {N_CFG_ITEMS, PagersCfgItems}
2187 };