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