1 /* -*-c-*- */
2 /*
3 * This module is all new
4 * by Rob Nation
5 */
6
7 /* This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see: <http://www.gnu.org/licenses/>
19 */
20
21 /*
22 *
23 * fvwm pager handling code
24 *
25 */
26
27 #include "config.h"
28
29 #include <stdio.h>
30 #include <signal.h>
31
32 #include <X11/Xlib.h>
33 #include <X11/Xutil.h>
34 #include <X11/Xproto.h>
35 #include <X11/Xatom.h>
36 #include <X11/Intrinsic.h>
37 #include <X11/keysym.h>
38
39 #include "libs/fvwmlib.h"
40 #include "libs/FScreen.h"
41 #include "libs/FShape.h"
42 #include "libs/Module.h"
43 #include "libs/Colorset.h"
44 #include "libs/Graphics.h"
45 #include "fvwm/fvwm.h"
46 #include "libs/PictureGraphics.h"
47 #include "FvwmPager.h"
48
49
50 extern ScreenInfo Scr;
51 extern Display *dpy;
52
53 Pixel back_pix, fore_pix, hi_pix;
54 Pixel focus_pix;
55 Pixel focus_fore_pix;
56 extern int windowcolorset, activecolorset;
57 extern Pixel win_back_pix, win_fore_pix, win_hi_back_pix, win_hi_fore_pix;
58 extern Bool win_pix_set, win_hi_pix_set;
59 extern int window_w, window_h,window_x,window_y,usposition,uselabel,xneg,yneg;
60 extern int StartIconic;
61 extern int MiniIcons;
62 extern int LabelsBelow;
63 extern int ShapeLabels;
64 extern int ShowBalloons, ShowPagerBalloons, ShowIconBalloons;
65 extern char *BalloonFormatString;
66 extern char *WindowLabelFormat;
67 extern char *PagerFore, *PagerBack, *HilightC;
68 extern char *BalloonFore, *BalloonBack, *BalloonBorderColor;
69 extern Window BalloonView;
70 extern unsigned int WindowBorderWidth;
71 extern unsigned int MinSize;
72 extern Bool WindowBorders3d;
73 extern Bool UseSkipList;
74 extern FvwmPicture *PixmapBack;
75 extern FvwmPicture *HilightPixmap;
76 extern int HilightDesks;
77 extern char fAlwaysCurrentDesk;
78
79 extern int MoveThreshold;
80
81 extern int icon_w, icon_h, icon_x, icon_y, icon_xneg, icon_yneg;
82 FlocaleFont *Ffont, *FwindowFont;
83 FlocaleWinString *FwinString;
84
85 extern PagerWindow *Start;
86 extern PagerWindow *FocusWin;
87 static Atom wm_del_win;
88
89 extern char *MyName;
90
91 extern int desk1, desk2, ndesks;
92 extern int Rows,Columns;
93 extern int fd[2];
94
95 int desk_w = 0;
96 int desk_h = 0;
97 int label_h = 0;
98
99 DeskInfo *Desks;
100 int Wait = 0;
101 int FvwmErrorHandler(Display *, XErrorEvent *);
102 extern Bool is_transient;
103 extern Bool do_ignore_next_button_release;
104 extern Bool use_dashed_separators;
105 extern Bool use_no_separators;
106
107
108 /* assorted gray bitmaps for decorative borders */
109 #define g_width 2
110 #define g_height 2
111 static char g_bits[] = {0x02, 0x01};
112
113 #define l_g_width 4
114 #define l_g_height 2
115 static char l_g_bits[] = {0x08, 0x02};
116
117 #define s_g_width 4
118 #define s_g_height 4
119 static char s_g_bits[] = {0x01, 0x02, 0x04, 0x08};
120
121 #define label_border g_width
122
123 Window icon_win; /* icon window */
124
125 static int MyVx, MyVy; /* copy of Scr.Vx/y for drag logic */
126
127 static char *GetBalloonLabel(const PagerWindow *pw,const char *fmt);
128 extern void ExitPager(void);
129
130 Pixmap default_pixmap = None;
131
132 #ifdef DEBUG
133 #define MYFPRINTF(X) \
134 fprintf X;\
135 fflush (stderr);
136 #else
137 #define MYFPRINTF(X)
138 #endif
139
140
141 #define MAX_UNPROCESSED_MESSAGES 1
142 /* sums up pixels to scroll. If do_send_message is True a Scroll command is
143 * sent back to fvwm. The function shall be called with is_message_recieved
144 * True when the Scroll command has been processed by fvwm. This is checked
145 * by talking to ourself. */
do_scroll(int sx,int sy,Bool do_send_message,Bool is_message_recieved)146 static void do_scroll(int sx, int sy, Bool do_send_message,
147 Bool is_message_recieved)
148 {
149 static int psx = 0;
150 static int psy = 0;
151 static int messages_sent = 0;
152 char command[256];
153 psx+=sx;
154 psy+=sy;
155 if (is_message_recieved)
156 {
157 /* There might be other modules with the same name, or someone
158 might send ScrollDone other than the module, so just treat
159 any negative count as zero. */
160 if (--messages_sent < 0)
161 {
162 messages_sent = 0;
163 }
164 }
165 if ((do_send_message || messages_sent < MAX_UNPROCESSED_MESSAGES) &&
166 ( psx != 0 || psy != 0 ))
167 {
168 sprintf(command, "Scroll %dp %dp", psx, psy);
169 SendText(fd, command, 0);
170 messages_sent++;
171 SendText(fd, "Send_Reply ScrollDone", 0);
172 psx = 0;
173 psy = 0;
174 }
175 }
176
HandleScrollDone(void)177 void HandleScrollDone(void)
178 {
179 do_scroll(0, 0, True, True);
180 }
181
182 typedef struct
183 {
184 int event_type;
185 XEvent *ret_last_event;
186 } _weed_window_events_args;
187
_pred_weed_window_events(Display * display,XEvent * current_event,XPointer arg)188 static int _pred_weed_window_events(
189 Display *display, XEvent *current_event, XPointer arg)
190 {
191 _weed_window_events_args *args = (_weed_window_events_args *)arg;
192
193 if (current_event->type == args->event_type)
194 {
195 if (args->ret_last_event != NULL)
196 {
197 *args->ret_last_event = *current_event;
198 }
199
200 return 1;
201 }
202
203 return 0;
204 }
205
206 /* discard certain events on a window */
discard_events(long event_type,Window w,XEvent * last_ev)207 static void discard_events(long event_type, Window w, XEvent *last_ev)
208 {
209 _weed_window_events_args args;
210
211 XSync(dpy, 0);
212 args.event_type = event_type;
213 args.ret_last_event = last_ev;
214 FWeedIfWindowEvents(dpy, w, _pred_weed_window_events, (XPointer)&args);
215
216 return;
217 }
218
219 /*
220 *
221 * Procedure:
222 * CalcGeom - calculates the size and position of a mini-window
223 * given the real window size.
224 * You can always tell bad code by the size of the comments.
225 */
CalcGeom(PagerWindow * t,int win_w,int win_h,int * x_ret,int * y_ret,int * w_ret,int * h_ret)226 static void CalcGeom(PagerWindow *t, int win_w, int win_h,
227 int *x_ret, int *y_ret, int *w_ret, int *h_ret)
228 {
229 int virt, virt2, edge, edge2, size, page, over;
230
231 /* coordinate of left hand edge on virtual desktop */
232 virt = Scr.Vx + t->x;
233
234 /* position of left hand edge of mini-window on pager window */
235 edge = (virt * win_w) / Scr.VWidth;
236
237 /* absolute coordinate of right hand edge on virtual desktop */
238 virt += t->width - 1;
239
240 /* to calculate the right edge, mirror the window and use the same
241 * calculations as for the left edge for consistency. */
242 virt2 = Scr.VWidth - 1 - virt;
243 edge2 = (virt2 * win_w) / Scr.VWidth;
244
245 /* then mirror it back to get the real coordinate */
246 edge2 = win_w - 1 - edge2;
247
248 /* Calculate the mini-window's width by subtracting its LHS
249 * from its RHS. This theoretically means that the width will
250 * vary slightly as the window travels around the screen, but
251 * this way ensures that the mini-windows in the pager match
252 * the actual screen layout. */
253 size = edge2 - edge + 1;
254
255 /* Make size big enough to be visible */
256 if (size < MinSize) {
257 size = MinSize;
258 /* this mini-window has to be grown to be visible
259 * which way it grows depends on some magic:
260 * normally it will grow right but if the window is on the right hand
261 * edge of a page it should be grown left so that the pager looks better */
262
263 /* work out the page that the right hand edge is on */
264 page = virt / Scr.MyDisplayWidth;
265
266 /* if the left edge is on the same page then possibly move it left */
267 if (page == ((virt - t->width + 1) / Scr.MyDisplayWidth)) {
268 /* calculate how far the mini-window right edge overlaps the page line */
269 /* beware that the "over" is actually one greater than on screen, but
270 this discrepancy is catered for in the next two lines */
271 over = edge + size - ((page + 1) * win_w * Scr.MyDisplayWidth) /
272 Scr.VWidth;
273
274 /* if the mini-window right edge is beyond the mini-window pager grid */
275 if (over > 0) {
276 /* move it left by the amount of pager grid overlap (!== the growth) */
277 edge -= over;
278 }
279 }
280 }
281 /* fill in return values */
282 *x_ret = edge;
283 *w_ret = size;
284
285 /* same code for y axis */
286 virt = Scr.Vy + t->y;
287 edge = (virt * win_h) / Scr.VHeight;
288 virt += t->height - 1;
289 virt2 = Scr.VHeight - 1 - virt;
290 edge2 = (virt2 * win_h) / Scr.VHeight;
291 edge2 = win_h - 1 - edge2;
292 size = edge2 - edge + 1;
293 if (size < MinSize)
294 {
295 size = MinSize;
296 page = virt / Scr.MyDisplayHeight;
297 if (page == ((virt - t->height + 1) / Scr.MyDisplayHeight)) {
298 over = edge + size - ((page + 1) * win_h * Scr.MyDisplayHeight) /
299 Scr.VHeight;
300 if (over > 0)
301 edge -= over;
302 }
303 }
304 *y_ret = edge;
305 *h_ret = size;
306 }
307
308 /*
309 *
310 * Procedure:
311 * Initialize_viz_pager - creates a temp window of the correct visual
312 * so that pixmaps may be created for use with the main window
313 */
initialize_viz_pager(void)314 void initialize_viz_pager(void)
315 {
316 XSetWindowAttributes attr;
317 XGCValues xgcv;
318
319 /* FIXME: I think that we only need that Pdepth ==
320 * DefaultDepth(dpy, Scr.screen) to use the Scr.Root for Scr.Pager_w */
321 if (Pdefault)
322 {
323 Scr.Pager_w = Scr.Root;
324 }
325 else
326 {
327 attr.background_pixmap = None;
328 attr.border_pixel = 0;
329 attr.colormap = Pcmap;
330 Scr.Pager_w = XCreateWindow(
331 dpy, Scr.Root, -10, -10, 10, 10, 0, Pdepth,
332 InputOutput, Pvisual,
333 CWBackPixmap|CWBorderPixel|CWColormap, &attr);
334 Scr.NormalGC = fvwmlib_XCreateGC(dpy, Scr.Pager_w, 0, &xgcv);
335 }
336 Scr.NormalGC = fvwmlib_XCreateGC(dpy, Scr.Pager_w, 0, NULL);
337
338 xgcv.plane_mask = AllPlanes;
339 Scr.MiniIconGC = fvwmlib_XCreateGC(
340 dpy, Scr.Pager_w, GCPlaneMask, &xgcv);
341 Scr.black = GetColor("Black");
342
343 /* Transparent background are only allowed when the depth matched the
344 * root */
345 if (Pdepth == DefaultDepth(dpy, Scr.screen))
346 {
347 default_pixmap = ParentRelative;
348 }
349
350 return;
351 }
352
353 /* see also change colorset */
draw_desk_background(int i,int page_w,int page_h)354 void draw_desk_background(int i, int page_w, int page_h)
355 {
356 if (Desks[i].colorset > -1)
357 {
358 XSetWindowBorder(
359 dpy, Desks[i].title_w, Colorset[Desks[i].colorset].fg);
360 XSetWindowBorder(
361 dpy, Desks[i].w, Colorset[Desks[i].colorset].fg);
362 XSetForeground(
363 dpy, Desks[i].NormalGC,Colorset[Desks[i].colorset].fg);
364 XSetForeground(
365 dpy, Desks[i].DashedGC,Colorset[Desks[i].colorset].fg);
366 if (uselabel)
367 {
368 if (CSET_IS_TRANSPARENT(Desks[i].colorset))
369 {
370 SetWindowBackground(
371 dpy, Desks[i].title_w,
372 desk_w, label_h,
373 &Colorset[Desks[i].colorset],
374 Pdepth,
375 Scr.NormalGC, True);
376 }
377 else
378 {
379 SetWindowBackground(
380 dpy, Desks[i].title_w, desk_w,
381 desk_h + label_h,
382 &Colorset[Desks[i].colorset], Pdepth,
383 Scr.NormalGC, True);
384 }
385 }
386 if (label_h != 0 && uselabel && !LabelsBelow &&
387 !CSET_IS_TRANSPARENT(Desks[i].colorset))
388 {
389 SetWindowBackgroundWithOffset(
390 dpy, Desks[i].w, 0, -label_h, desk_w,
391 desk_h + label_h, &Colorset[Desks[i].colorset],
392 Pdepth, Scr.NormalGC, True);
393 }
394 else
395 {
396 if (CSET_IS_TRANSPARENT(Desks[i].colorset))
397 {
398 SetWindowBackground(
399 dpy, Desks[i].w, desk_w, desk_h,
400 &Colorset[Desks[i].colorset], Pdepth,
401 Scr.NormalGC, True);
402 }
403 else
404 {
405 SetWindowBackground(
406 dpy, Desks[i].w, desk_w,
407 desk_h + label_h,
408 &Colorset[Desks[i].colorset],
409 Pdepth, Scr.NormalGC, True);
410 }
411 }
412 }
413 XClearArea(dpy,Desks[i].w, 0, 0, 0, 0,True);
414 if (Desks[i].highcolorset > -1)
415 {
416 XSetForeground(
417 dpy, Desks[i].HiliteGC,
418 Colorset[Desks[i].highcolorset].bg);
419 XSetForeground(
420 dpy, Desks[i].rvGC, Colorset[Desks[i].highcolorset].fg);
421 if (HilightDesks)
422 {
423 SetWindowBackground(
424 dpy, Desks[i].CPagerWin, page_w, page_h,
425 &Colorset[Desks[i].highcolorset], Pdepth,
426 Scr.NormalGC, True);
427 }
428 }
429 if (uselabel)
430 {
431 XClearArea(dpy,Desks[i].title_w, 0, 0, 0, 0,True);
432 }
433
434 return;
435 }
436
437 /*
438 *
439 * Procedure:
440 * Initialize_pager - creates the pager window, if needed
441 *
442 * Inputs:
443 * x,y location of the window
444 *
445 */
446 char *pager_name = "Fvwm Pager";
447 XSizeHints sizehints =
448 {
449 (PMinSize | PResizeInc | PBaseSize | PWinGravity),
450 0, 0, 100, 100, /* x, y, width and height */
451 1, 1, /* Min width and height */
452 0, 0, /* Max width and height */
453 1, 1, /* Width and height increments */
454 {0, 0}, {0, 0}, /* Aspect ratio - not used */
455 1, 1, /* base size */
456 (NorthWestGravity) /* gravity */
457 };
458
initialize_balloon_window(void)459 void initialize_balloon_window(void)
460 {
461 XGCValues xgcv;
462 unsigned long valuemask;
463 XSetWindowAttributes attributes;
464 extern int BalloonBorderWidth;
465
466 /* create balloon window
467 -- ric@giccs.georgetown.edu */
468 if (!ShowBalloons)
469 {
470 Scr.balloon_w = None;
471 return;
472 }
473 valuemask = CWOverrideRedirect | CWEventMask | CWColormap;
474 /* tell WM to ignore this window */
475 attributes.override_redirect = True;
476 attributes.event_mask = ExposureMask;
477 attributes.colormap = Pcmap;
478 /* now create the window */
479 Scr.balloon_w = XCreateWindow(
480 dpy, Scr.Root, 0, 0, /* coords set later */ 1, 1,
481 BalloonBorderWidth, Pdepth, InputOutput, Pvisual, valuemask,
482 &attributes);
483 Scr.balloon_gc = fvwmlib_XCreateGC(dpy, Scr.balloon_w, 0, &xgcv);
484 /* Make sure we don't get balloons initially with the Icon option. */
485 ShowBalloons = ShowPagerBalloons;
486
487 return;
488 }
489
initialize_pager(void)490 void initialize_pager(void)
491 {
492 XWMHints wmhints;
493 XClassHint class1;
494 XTextProperty name;
495 unsigned long valuemask;
496 XSetWindowAttributes attributes;
497 extern char *WindowBack, *WindowFore, *WindowHiBack, *WindowHiFore;
498 extern char *BalloonFont;
499 extern char *font_string, *smallFont;
500 int n,m,w,h,i,x,y;
501 XGCValues gcv;
502 char dash_list[2];
503 FlocaleFont *balloon_font;
504
505 /* I don't think that this is necessary - just let pager die */
506 /* domivogt (07-mar-1999): But it is! A window being moved in the pager
507 * might die at any moment causing the Xlib calls to generate BadMatch
508 * errors. Without an error handler the pager will die! */
509 XSetErrorHandler(FvwmErrorHandler);
510
511 wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False);
512
513 /* load the font */
514 /* Note: "font" is always created, whether labels are used or not
515 because a GC below is set to use a font. dje Dec 2001.
516 OK, I fixed the GC below, but now something else is blowing up.
517 Right now, I've got to do some Real Life stuff, so this kludge is
518 in place, its still better than I found it.
519 I hope that I've fixed this (olicha)
520 */
521 Ffont = FlocaleLoadFont(dpy, font_string, MyName);
522
523 label_h = (uselabel) ? Ffont->height + 2 : 0;
524
525 /* init our Flocale window string */
526 FlocaleAllocateWinString(&FwinString);
527
528 /* Check that shape extension exists. */
529 if (FHaveShapeExtension && ShapeLabels)
530 {
531 ShapeLabels = (FShapesSupported) ? 1 : 0;
532 }
533
534 if(smallFont != NULL)
535 {
536 FwindowFont = FlocaleLoadFont(dpy, smallFont, MyName);
537 }
538
539 /* Load the colors */
540 fore_pix = GetColor(PagerFore);
541 back_pix = GetColor(PagerBack);
542 hi_pix = GetColor(HilightC);
543
544 if (windowcolorset >= 0)
545 {
546 win_back_pix = Colorset[windowcolorset].bg;
547 win_fore_pix = Colorset[windowcolorset].fg;
548 win_pix_set = True;
549 }
550 else if (WindowBack && WindowFore)
551 {
552 win_back_pix = GetColor(WindowBack);
553 win_fore_pix = GetColor(WindowFore);
554 win_pix_set = True;
555 }
556
557 if (activecolorset >= 0)
558 {
559 win_hi_back_pix = Colorset[activecolorset].bg;
560 win_hi_fore_pix = Colorset[activecolorset].fg;
561 win_hi_pix_set = True;
562 }
563 else if (WindowHiBack && WindowHiFore)
564 {
565 win_hi_back_pix = GetColor(WindowHiBack);
566 win_hi_fore_pix = GetColor(WindowHiFore);
567 win_hi_pix_set = True;
568 }
569
570 /* Load pixmaps for mono use */
571 if(Pdepth<2)
572 {
573 Scr.gray_pixmap =
574 XCreatePixmapFromBitmapData(dpy,Scr.Pager_w,g_bits, g_width,g_height,
575 fore_pix,back_pix,Pdepth);
576 Scr.light_gray_pixmap =
577 XCreatePixmapFromBitmapData(dpy,Scr.Pager_w,l_g_bits,l_g_width,
578 l_g_height,
579 fore_pix,back_pix,Pdepth);
580 Scr.sticky_gray_pixmap =
581 XCreatePixmapFromBitmapData(dpy,Scr.Pager_w,s_g_bits,s_g_width,
582 s_g_height,
583 fore_pix,back_pix,Pdepth);
584 }
585
586
587 n = Scr.VxMax / Scr.MyDisplayWidth;
588 m = Scr.VyMax / Scr.MyDisplayHeight;
589
590 /* Size the window */
591 if(Rows < 0)
592 {
593 if(Columns < 0)
594 {
595 Columns = ndesks;
596 Rows = 1;
597 }
598 else
599 {
600 Rows = ndesks/Columns;
601 if(Rows*Columns < ndesks)
602 Rows++;
603 }
604 }
605 if(Columns < 0)
606 {
607 if (Rows == 0)
608 Rows = 1;
609 Columns = ndesks/Rows;
610 if(Rows*Columns < ndesks)
611 Columns++;
612 }
613
614 if(Rows*Columns < ndesks)
615 {
616 if (Columns == 0)
617 Columns = 1;
618 Rows = ndesks/Columns;
619 if (Rows*Columns < ndesks)
620 Rows++;
621 }
622
623 sizehints.width_inc = Columns*(n+1);
624 sizehints.height_inc = Rows*(m+1);
625 sizehints.base_width = Columns * n + Columns - 1;
626 sizehints.base_height = Rows * (m + label_h + 1) - 1;
627 if (window_w > 0)
628 {
629 window_w = (window_w - sizehints.base_width) / sizehints.width_inc;
630 window_w = window_w * sizehints.width_inc + sizehints.base_width;
631 }
632 else
633 {
634 window_w = Columns * (Scr.VWidth / Scr.VScale + n) + Columns - 1;
635 }
636 if (window_h > 0)
637 {
638 window_h = (window_h - sizehints.base_height) / sizehints.height_inc;
639 window_h = window_h * sizehints.height_inc + sizehints.base_height;
640 }
641 else
642 {
643 window_h = Rows * (Scr.VHeight / Scr.VScale + m + label_h + 1) - 1;
644 }
645 desk_w = (window_w - Columns + 1) / Columns;
646 desk_h = (window_h - Rows * label_h - Rows + 1) / Rows;
647 if (is_transient)
648 {
649 rectangle screen_g;
650 fscreen_scr_arg fscr;
651
652 fscr.xypos.x = window_x;
653 fscr.xypos.y = window_y;
654 FScreenGetScrRect(
655 &fscr, FSCREEN_XYPOS,
656 &screen_g.x, &screen_g.y, &screen_g.width, &screen_g.height);
657 if (window_w + window_x > screen_g.x + screen_g.width)
658 {
659 window_x = screen_g.x + screen_g.width - Scr.MyDisplayWidth;
660 xneg = 1;
661 }
662 if (window_h + window_y > screen_g.y + screen_g.height)
663 {
664 window_y = screen_g.y + screen_g.height - Scr.MyDisplayHeight;
665 yneg = 1;
666 }
667 }
668 if (xneg)
669 {
670 sizehints.win_gravity = NorthEastGravity;
671 window_x = Scr.MyDisplayWidth - window_w + window_x;
672 }
673 if (yneg)
674 {
675 window_y = Scr.MyDisplayHeight - window_h + window_y;
676 if(sizehints.win_gravity == NorthEastGravity)
677 sizehints.win_gravity = SouthEastGravity;
678 else
679 sizehints.win_gravity = SouthWestGravity;
680 }
681 sizehints.width = window_w;
682 sizehints.height = window_h;
683
684 if(usposition)
685 sizehints.flags |= USPosition;
686
687 valuemask = (CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask);
688 attributes.background_pixmap = default_pixmap;
689 attributes.border_pixel = 0;
690 attributes.colormap = Pcmap;
691 attributes.event_mask = (StructureNotifyMask);
692
693 /* destroy the temp window first, don't worry if it's the Root */
694 if (Scr.Pager_w != Scr.Root)
695 XDestroyWindow(dpy, Scr.Pager_w);
696 Scr.Pager_w = XCreateWindow (dpy, Scr.Root, window_x, window_y, window_w,
697 window_h, 0, Pdepth, InputOutput, Pvisual,
698 valuemask, &attributes);
699 XSetWMProtocols(dpy,Scr.Pager_w,&wm_del_win,1);
700 /* hack to prevent mapping on wrong screen with StartsOnScreen */
701 FScreenMangleScreenIntoUSPosHints(FSCREEN_XYPOS, &sizehints);
702 XSetWMNormalHints(dpy,Scr.Pager_w,&sizehints);
703 if (is_transient)
704 {
705 XSetTransientForHint(dpy, Scr.Pager_w, Scr.Root);
706 }
707
708 if((desk1==desk2)&&(Desks[0].label != NULL))
709 {
710 if (FlocaleTextListToTextProperty(
711 dpy, &Desks[0].label, 1, XStdICCTextStyle, &name) == 0)
712 {
713 fprintf(stderr,"%s: fatal error: cannot allocate desk name", MyName);
714 exit(0);
715 }
716 }
717 else
718 {
719 if (FlocaleTextListToTextProperty(
720 dpy, &Desks[0].label, 1, XStdICCTextStyle, &name) == 0)
721 {
722 fprintf(stderr,"%s: fatal error: cannot allocate pager name", MyName);
723 exit(0);
724 }
725 }
726
727 attributes.event_mask = (StructureNotifyMask| ExposureMask);
728 if(icon_w < 1)
729 icon_w = (window_w - Columns+1)/Columns;
730 if(icon_h < 1)
731 icon_h = (window_h - Rows* label_h - Rows + 1)/Rows;
732
733 icon_w = (icon_w / (n+1)) *(n+1)+n;
734 icon_h = (icon_h / (m+1)) *(m+1)+m;
735 icon_win = XCreateWindow (dpy, Scr.Root, window_x, window_y, icon_w, icon_h,
736 0, Pdepth, InputOutput, Pvisual, valuemask,
737 &attributes);
738 XGrabButton(dpy, 1, AnyModifier, icon_win,
739 True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask,
740 GrabModeAsync, GrabModeAsync, None,
741 None);
742 XGrabButton(dpy, 2, AnyModifier, icon_win,
743 True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask,
744 GrabModeAsync, GrabModeAsync, None,
745 None);
746 XGrabButton(dpy, 3, AnyModifier, icon_win,
747 True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask,
748 GrabModeAsync, GrabModeAsync, None,
749 None);
750
751 if(!StartIconic)
752 wmhints.initial_state = NormalState;
753 else
754 wmhints.initial_state = IconicState;
755 wmhints.flags = 0;
756 if (icon_x != -10000)
757 {
758 if (icon_xneg)
759 icon_x = Scr.MyDisplayWidth + icon_x - icon_w;
760 if (icon_y != -10000)
761 {
762 if (icon_yneg)
763 icon_y = Scr.MyDisplayHeight + icon_y - icon_h;
764 }
765 else
766 {
767 icon_y = 0;
768 }
769 icon_xneg = 0;
770 icon_yneg = 0;
771 wmhints.icon_x = icon_x;
772 wmhints.icon_y = icon_y;
773 wmhints.flags = IconPositionHint;
774 }
775 wmhints.icon_window = icon_win;
776 wmhints.input = False;
777 wmhints.flags |= InputHint | StateHint | IconWindowHint;
778
779 class1.res_name = MyName;
780 class1.res_class = "FvwmPager";
781
782 XSetWMProperties(dpy,Scr.Pager_w,&name,&name,NULL,0,
783 &sizehints,&wmhints,&class1);
784 XFree((char *)name.value);
785
786 /* change colour/font for labelling mini-windows */
787 XSetForeground(dpy, Scr.NormalGC, focus_fore_pix);
788
789 if (FwindowFont != NULL && FwindowFont->font != NULL)
790 XSetFont(dpy, Scr.NormalGC, FwindowFont->font->fid);
791
792 /* create the 3d bevel GC's if necessary */
793 if (windowcolorset >= 0) {
794 gcv.foreground = Colorset[windowcolorset].hilite;
795 Scr.whGC = fvwmlib_XCreateGC(dpy, Scr.Pager_w, GCForeground, &gcv);
796 gcv.foreground = Colorset[windowcolorset].shadow;
797 Scr.wsGC = fvwmlib_XCreateGC(dpy, Scr.Pager_w, GCForeground, &gcv);
798 }
799 if (activecolorset >= 0) {
800 gcv.foreground = Colorset[activecolorset].hilite;
801 Scr.ahGC = fvwmlib_XCreateGC(dpy, Scr.Pager_w, GCForeground, &gcv);
802 gcv.foreground = Colorset[activecolorset].shadow;
803 Scr.asGC = fvwmlib_XCreateGC(dpy, Scr.Pager_w, GCForeground, &gcv);
804 }
805
806 balloon_font = FlocaleLoadFont(dpy, BalloonFont, MyName);
807 for(i=0;i<ndesks;i++)
808 {
809 w = window_w / Columns;
810 h = window_h / Rows;
811 x = (w + 1) * (i % Columns);
812 y = (h + 1) * (i / Columns);
813
814 /* create the GC for desk labels */
815 gcv.foreground = (Desks[i].colorset < 0) ? fore_pix
816 : Colorset[Desks[i].colorset].fg;
817 if (uselabel && Ffont && Ffont->font) {
818 gcv.font = Ffont->font->fid;
819 Desks[i].NormalGC =
820 fvwmlib_XCreateGC(dpy, Scr.Pager_w, GCForeground | GCFont, &gcv);
821 } else {
822 Desks[i].NormalGC =
823 fvwmlib_XCreateGC(dpy, Scr.Pager_w, GCForeground, &gcv);
824 }
825 /* create the active desk hilite GC */
826 if(Pdepth < 2)
827 gcv.foreground = fore_pix;
828 else
829 gcv.foreground = (Desks[i].highcolorset < 0) ? hi_pix
830 : Colorset[Desks[i].highcolorset].bg;
831 Desks[i].HiliteGC = fvwmlib_XCreateGC(dpy, Scr.Pager_w, GCForeground, &gcv);
832
833 /* create the hilight desk title drawing GC */
834 if ((Pdepth < 2) || (fore_pix == hi_pix))
835 gcv.foreground = (Desks[i].highcolorset < 0) ? back_pix
836 : Colorset[Desks[i].highcolorset].fg;
837 else
838 gcv.foreground = (Desks[i].highcolorset < 0) ? fore_pix
839 : Colorset[Desks[i].highcolorset].fg;
840
841 if (uselabel && Ffont && Ffont->font) {
842 Desks[i].rvGC =
843 fvwmlib_XCreateGC(dpy, Scr.Pager_w, GCForeground | GCFont, &gcv);
844 } else {
845 Desks[i].rvGC =
846 fvwmlib_XCreateGC(dpy, Scr.Pager_w, GCForeground, &gcv);
847 }
848 /* create the virtual page boundary GC */
849 gcv.foreground = (Desks[i].colorset < 0) ? fore_pix
850 : Colorset[Desks[i].colorset].fg;
851 gcv.line_width = 1;
852 gcv.line_style = (use_dashed_separators) ? LineOnOffDash : LineSolid;
853 Desks[i].DashedGC =
854 fvwmlib_XCreateGC(
855 dpy, Scr.Pager_w, GCForeground | GCLineStyle | GCLineWidth, &gcv);
856 if (use_dashed_separators)
857 {
858 /* Although this should already be the default for a freshly created GC,
859 * some X servers do not draw properly dashed lines if the dash style is
860 * not set explicitly. */
861 dash_list[0] = 4;
862 dash_list[1] = 4;
863 XSetDashes(dpy, Desks[i].DashedGC, 0, dash_list, 2);
864 }
865
866 valuemask = (CWBorderPixel | CWColormap | CWEventMask);
867 if (Desks[i].colorset >= 0 && Colorset[Desks[i].colorset].pixmap)
868 {
869 valuemask |= CWBackPixmap;
870 attributes.background_pixmap = Colorset[Desks[i].colorset].pixmap;
871 }
872 else
873 {
874 valuemask |= CWBackPixel;
875 attributes.background_pixel = (Desks[i].colorset < 0) ?
876 (Desks[i].Dcolor ? GetColor(Desks[i].Dcolor) : back_pix)
877 : Colorset[Desks[i].colorset].bg;
878 }
879
880 attributes.border_pixel = (Desks[i].colorset < 0) ? fore_pix
881 : Colorset[Desks[i].colorset].fg;
882 attributes.event_mask = (ExposureMask | ButtonReleaseMask);
883 Desks[i].title_w = XCreateWindow(
884 dpy, Scr.Pager_w, x - 1, y - 1, w, h, 1, CopyFromParent, InputOutput,
885 CopyFromParent, valuemask, &attributes);
886 attributes.event_mask = (ExposureMask | ButtonReleaseMask |
887 ButtonPressMask |ButtonMotionMask);
888 /* or just: desk_h = h - label_h; */
889 desk_h = (window_h - Rows * label_h - Rows + 1) / Rows;
890
891 valuemask &= ~(CWBackPixel);
892
893
894 if (Desks[i].colorset > -1 &&
895 Colorset[Desks[i].colorset].pixmap)
896 {
897 valuemask |= CWBackPixmap;
898 attributes.background_pixmap = None; /* set later */
899 }
900 else if (Desks[i].bgPixmap)
901 {
902 valuemask |= CWBackPixmap;
903 attributes.background_pixmap = Desks[i].bgPixmap->picture;
904 }
905 else if (Desks[i].Dcolor)
906 {
907 valuemask |= CWBackPixel;
908 attributes.background_pixel = GetColor(Desks[i].Dcolor);
909 }
910 else if (PixmapBack)
911 {
912 valuemask |= CWBackPixmap;
913 attributes.background_pixmap = PixmapBack->picture;
914 }
915 else
916 {
917 valuemask |= CWBackPixel;
918 attributes.background_pixel = (Desks[i].colorset < 0) ? back_pix
919 : Colorset[Desks[i].colorset].bg;
920 }
921
922 Desks[i].w = XCreateWindow(
923 dpy, Desks[i].title_w, x - 1, LabelsBelow ? -1 : label_h - 1, w, desk_h,
924 1, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes);
925
926 if (HilightDesks)
927 {
928 valuemask &= ~(CWBackPixel | CWBackPixmap);
929
930 attributes.event_mask = 0;
931
932 if (Desks[i].highcolorset > -1 &&
933 Colorset[Desks[i].highcolorset].pixmap)
934 {
935 valuemask |= CWBackPixmap;
936 attributes.background_pixmap = None; /* set later */
937 }
938 else if (HilightPixmap)
939 {
940 valuemask |= CWBackPixmap;
941 attributes.background_pixmap = HilightPixmap->picture;
942 }
943 else
944 {
945 valuemask |= CWBackPixel;
946 attributes.background_pixel = (Desks[i].highcolorset < 0) ? hi_pix
947 : Colorset[Desks[i].highcolorset].bg;
948 }
949
950 w = w / (n + 1);
951 h = desk_h / (m + 1);
952 Desks[i].CPagerWin=XCreateWindow(dpy, Desks[i].w, -32768, -32768, w, h, 0,
953 CopyFromParent, InputOutput,
954 CopyFromParent, valuemask, &attributes);
955 draw_desk_background(i, w, h);
956 XMapRaised(dpy,Desks[i].CPagerWin);
957 }
958 else
959 {
960 draw_desk_background(i, 0, 0);
961 }
962
963 XMapRaised(dpy,Desks[i].w);
964 XMapRaised(dpy,Desks[i].title_w);
965
966 /* get font for balloon */
967 Desks[i].balloon.Ffont = balloon_font;
968 if (Desks[i].balloon.Ffont == NULL)
969 {
970 fprintf(stderr, "%s: No fonts available, giving up!.\n", MyName);
971 }
972 Desks[i].balloon.height = Desks[i].balloon.Ffont->height + 1;
973 }
974 initialize_balloon_window();
975 XMapRaised(dpy,Scr.Pager_w);
976 }
977
978
UpdateWindowShape(void)979 void UpdateWindowShape(void)
980 {
981 if (FHaveShapeExtension)
982 {
983 int i, j, cnt, shape_count, x_pos, y_pos;
984 XRectangle *shape;
985
986 if (!ShapeLabels || !uselabel || label_h<=0)
987 return;
988
989 shape_count =
990 ndesks + ((Scr.CurrentDesk < desk1 || Scr.CurrentDesk >desk2) ? 0 : 1);
991
992 shape = (XRectangle *)alloca (shape_count * sizeof (XRectangle));
993
994 if (shape == NULL)
995 return;
996
997 cnt = 0;
998 y_pos = (LabelsBelow ? 0 : label_h);
999
1000 for (i = 0; i < Rows; ++i)
1001 {
1002 x_pos = 0;
1003 for (j = 0; j < Columns; ++j)
1004 {
1005 if (cnt < ndesks)
1006 {
1007 shape[cnt].x = x_pos;
1008 shape[cnt].y = y_pos;
1009 shape[cnt].width = desk_w + 1;
1010 shape[cnt].height = desk_h + 2;
1011
1012 if (cnt == Scr.CurrentDesk - desk1)
1013 {
1014 shape[ndesks].x = x_pos;
1015 shape[ndesks].y =
1016 (LabelsBelow ? y_pos + desk_h + 2 : y_pos - label_h);
1017 shape[ndesks].width = desk_w;
1018 shape[ndesks].height = label_h + 2;
1019 }
1020 }
1021 ++cnt;
1022 x_pos += desk_w + 1;
1023 }
1024 y_pos += desk_h + 2 + label_h;
1025 }
1026
1027 FShapeCombineRectangles(
1028 dpy, Scr.Pager_w, FShapeBounding, 0, 0, shape, shape_count, FShapeSet, 0);
1029 }
1030 }
1031
1032
1033
1034 /*
1035 *
1036 * Decide what to do about received X events
1037 *
1038 */
DispatchEvent(XEvent * Event)1039 void DispatchEvent(XEvent *Event)
1040 {
1041 int i,x,y;
1042 Window JunkRoot, JunkChild;
1043 Window w;
1044 int JunkX, JunkY;
1045 unsigned JunkMask;
1046 char keychar;
1047 KeySym keysym;
1048 Bool do_move_page = False;
1049 short dx = 0;
1050 short dy = 0;
1051
1052 switch(Event->xany.type)
1053 {
1054 case EnterNotify:
1055 HandleEnterNotify(Event);
1056 break;
1057 case LeaveNotify:
1058 if ( ShowBalloons )
1059 UnmapBalloonWindow();
1060 break;
1061 case ConfigureNotify:
1062 fev_sanitise_configure_notify(&Event->xconfigure);
1063 w = Event->xconfigure.window;
1064 discard_events(ConfigureNotify, Event->xconfigure.window, Event);
1065 fev_sanitise_configure_notify(&Event->xconfigure);
1066 if (w != icon_win)
1067 {
1068 /* icon_win is not handled here */
1069 discard_events(Expose, w, NULL);
1070 ReConfigure();
1071 }
1072 break;
1073 case Expose:
1074 HandleExpose(Event);
1075 break;
1076 case KeyPress:
1077 if (is_transient)
1078 {
1079 XLookupString(&(Event->xkey), &keychar, 1, &keysym, NULL);
1080 switch(keysym)
1081 {
1082 case XK_Up:
1083 dy = -100;
1084 do_move_page = True;
1085 break;
1086 case XK_Down:
1087 dy = 100;
1088 do_move_page = True;
1089 break;
1090 case XK_Left:
1091 dx = -100;
1092 do_move_page = True;
1093 break;
1094 case XK_Right:
1095 dx = 100;
1096 do_move_page = True;
1097 break;
1098 default:
1099 /* does not return */
1100 ExitPager();
1101 break;
1102 }
1103 if (do_move_page)
1104 {
1105 char command[64];
1106 sprintf(command,"Scroll %d %d", dx, dy);
1107 SendText(fd, command, 0);
1108 }
1109 }
1110 break;
1111 case ButtonRelease:
1112 if (do_ignore_next_button_release)
1113 {
1114 do_ignore_next_button_release = False;
1115 break;
1116 }
1117 if (Event->xbutton.button == 3)
1118 {
1119 for(i=0;i<ndesks;i++)
1120 {
1121 if(Event->xany.window == Desks[i].w)
1122 {
1123 if (FQueryPointer(dpy, Desks[i].w, &JunkRoot, &JunkChild,
1124 &JunkX, &JunkY,&x, &y, &JunkMask) == False)
1125 {
1126 /* pointer is on a different screen - that's okay here */
1127 }
1128 Scroll(desk_w, desk_h, x, y, i, False);
1129 }
1130 }
1131 if(Event->xany.window == icon_win)
1132 {
1133 if (FQueryPointer(dpy, icon_win, &JunkRoot, &JunkChild,
1134 &JunkX, &JunkY,&x, &y, &JunkMask) == False)
1135 {
1136 /* pointer is on a different screen - that's okay here */
1137 }
1138 Scroll(icon_w, icon_h, x, y, 0, True);
1139 }
1140 /* Flush any pending scroll operations */
1141 do_scroll(0, 0, True, False);
1142 }
1143 else if((Event->xbutton.button == 1)||
1144 (Event->xbutton.button == 2))
1145 {
1146 for(i=0;i<ndesks;i++)
1147 {
1148 if(Event->xany.window == Desks[i].w)
1149 SwitchToDeskAndPage(i,Event);
1150 else if(Event->xany.window == Desks[i].title_w)
1151 SwitchToDesk(i);
1152 }
1153 if(Event->xany.window == icon_win)
1154 {
1155 IconSwitchPage(Event);
1156 }
1157 }
1158 if (is_transient)
1159 {
1160 /* does not return */
1161 ExitPager();
1162 }
1163 break;
1164 case ButtonPress:
1165 do_ignore_next_button_release = False;
1166 if ( ShowBalloons )
1167 UnmapBalloonWindow();
1168 if (((Event->xbutton.button == 2)||
1169 ((Event->xbutton.button == 3)&&
1170 (Event->xbutton.state & Mod1Mask)))&&
1171 (Event->xbutton.subwindow != None))
1172 {
1173 MoveWindow(Event);
1174 }
1175 else if (Event->xbutton.button == 3)
1176 {
1177 /* save initial virtual desk position for drag */
1178 MyVx=Scr.Vx;
1179 MyVy=Scr.Vy;
1180 for(i=0;i<ndesks;i++)
1181 {
1182 if(Event->xany.window == Desks[i].w)
1183 {
1184 if (FQueryPointer(dpy, Desks[i].w, &JunkRoot, &JunkChild,
1185 &JunkX, &JunkY,&x, &y, &JunkMask) == False)
1186 {
1187 /* pointer is on a different screen - that's okay here */
1188 }
1189 Scroll(desk_w, desk_h, x, y, Scr.CurrentDesk, False);
1190 if (Scr.CurrentDesk != i + desk1)
1191 {
1192 Wait = 0;
1193 SwitchToDesk(i);
1194 }
1195 break;
1196 }
1197 }
1198 if(Event->xany.window == icon_win)
1199 {
1200 if (FQueryPointer(dpy, icon_win, &JunkRoot, &JunkChild,
1201 &JunkX, &JunkY,&x, &y, &JunkMask) == False)
1202 {
1203 /* pointer is on a different screen - that's okay here */
1204 }
1205 Scroll(icon_w, icon_h, x, y, 0, True);
1206 }
1207 }
1208 break;
1209 case MotionNotify:
1210 do_ignore_next_button_release = False;
1211 while(FCheckMaskEvent(dpy, PointerMotionMask | ButtonMotionMask,Event))
1212 ;
1213
1214 if(Event->xmotion.state & Button3MotionMask)
1215 {
1216 for(i=0;i<ndesks;i++)
1217 {
1218 if(Event->xany.window == Desks[i].w)
1219 {
1220 if (FQueryPointer(dpy, Desks[i].w, &JunkRoot, &JunkChild,
1221 &JunkX, &JunkY,&x, &y, &JunkMask) == False)
1222 {
1223 /* pointer is on a different screen - that's okay here */
1224 }
1225 Scroll(desk_w, desk_h, x, y, i, False);
1226 }
1227 }
1228 if(Event->xany.window == icon_win)
1229 {
1230 if (FQueryPointer(dpy, icon_win, &JunkRoot, &JunkChild,
1231 &JunkX, &JunkY,&x, &y, &JunkMask) == False)
1232 {
1233 /* pointer is on a different screen - that's okay here */
1234 }
1235 Scroll(icon_w, icon_h, x, y, 0, True);
1236 }
1237
1238 }
1239 break;
1240
1241 case ClientMessage:
1242 if ((Event->xclient.format==32) &&
1243 (Event->xclient.data.l[0]==wm_del_win))
1244 {
1245 /* does not return */
1246 ExitPager();
1247 }
1248 break;
1249 }
1250 }
1251
HandleEnterNotify(XEvent * Event)1252 void HandleEnterNotify(XEvent *Event)
1253
1254 {
1255 PagerWindow *t;
1256 Bool is_icon_view = False;
1257 extern Bool do_focus_on_enter;
1258
1259 if (!ShowBalloons && !do_focus_on_enter)
1260 /* nothing to do */
1261 return;
1262
1263 /* is this the best way to match X event window ID to PagerWindow ID? */
1264 for ( t = Start; t != NULL; t = t->next )
1265 {
1266 if ( t->PagerView == Event->xcrossing.window )
1267 {
1268 break;
1269 }
1270 if ( t->IconView == Event->xcrossing.window )
1271 {
1272 is_icon_view = True;
1273 break;
1274 }
1275 }
1276 if (t == NULL)
1277 {
1278 return;
1279 }
1280
1281 if (ShowBalloons)
1282 {
1283 MapBalloonWindow(t, is_icon_view);
1284 }
1285
1286 if (do_focus_on_enter)
1287 {
1288 SendText(fd, "Silent FlipFocus NoWarp", t->w);
1289 }
1290
1291 }
1292
get_expose_bound(XEvent * Event)1293 XRectangle get_expose_bound(XEvent *Event)
1294 {
1295 XRectangle r;
1296 int ex, ey, ex2, ey2;
1297
1298 ex = Event->xexpose.x;
1299 ey = Event->xexpose.y;
1300 ex2 = Event->xexpose.x + Event->xexpose.width;
1301 ey2 = Event->xexpose.y + Event->xexpose.height;
1302 while (FCheckTypedWindowEvent(dpy, Event->xany.window, Expose, Event))
1303 {
1304 ex = min(ex, Event->xexpose.x);
1305 ey = min(ey, Event->xexpose.y);
1306 ex2 = max(ex2, Event->xexpose.x + Event->xexpose.width);
1307 ey2= max(ey2 , Event->xexpose.y + Event->xexpose.height);
1308 }
1309 r.x = ex;
1310 r.y = ey;
1311 r.width = ex2-ex;
1312 r.height = ey2-ey;
1313 return r;
1314 }
1315
HandleExpose(XEvent * Event)1316 void HandleExpose(XEvent *Event)
1317 {
1318 int i;
1319 PagerWindow *t;
1320 XRectangle r;
1321
1322 /* it will be good to have full "clipping redraw". Do that for
1323 * desk label only for now */
1324 for(i=0;i<ndesks;i++)
1325 {
1326 /* ric@giccs.georgetown.edu */
1327 if (Event->xany.window == Desks[i].w ||
1328 Event->xany.window == Desks[i].title_w)
1329 {
1330 r = get_expose_bound(Event);
1331 DrawGrid(i, 0, Event->xany.window, &r);
1332 return;
1333 }
1334 }
1335 if (Event->xany.window == Scr.balloon_w)
1336 {
1337 DrawInBalloonWindow(Scr.balloon_desk);
1338 return;
1339 }
1340 if(Event->xany.window == icon_win)
1341 DrawIconGrid(0);
1342
1343 for (t = Start; t != NULL; t = t->next)
1344 {
1345 if (t->PagerView == Event->xany.window)
1346 {
1347 LabelWindow(t);
1348 PictureWindow(t);
1349 BorderWindow(t);
1350 }
1351 else if(t->IconView == Event->xany.window)
1352 {
1353 LabelIconWindow(t);
1354 PictureIconWindow(t);
1355 BorderIconWindow(t);
1356 }
1357 }
1358
1359 discard_events(Expose, Event->xany.window, NULL);
1360 }
1361
1362 /*
1363 *
1364 * Respond to a change in window geometry.
1365 *
1366 */
ReConfigure(void)1367 void ReConfigure(void)
1368 {
1369 Window root;
1370 unsigned border_width, depth;
1371 int n,m,w,h,n1,m1,x,y,i,j,k;
1372 int old_ww;
1373 int old_wh;
1374 int is_size_changed;
1375
1376 old_ww = window_w;
1377 old_wh = window_h;
1378 if (!XGetGeometry(dpy, Scr.Pager_w, &root, &x, &y, (unsigned *)&window_w,
1379 (unsigned *)&window_h, &border_width,&depth))
1380 {
1381 return;
1382 }
1383 is_size_changed = (old_ww != window_w || old_wh != window_h);
1384
1385 n1 = Scr.Vx / Scr.MyDisplayWidth;
1386 m1 = Scr.Vy / Scr.MyDisplayHeight;
1387 n = Scr.VxMax / Scr.MyDisplayWidth;
1388 m = Scr.VyMax / Scr.MyDisplayHeight;
1389
1390 sizehints.width_inc = Columns * (n + 1);
1391 sizehints.height_inc = Rows * (m + 1);
1392 sizehints.base_width = Columns * n + Columns - 1;
1393 sizehints.base_height = Rows*(m + label_h+1) - 1;
1394 sizehints.min_width = sizehints.base_width;
1395 sizehints.min_height = sizehints.base_height;
1396 if (window_w > 0)
1397 {
1398 window_w = (window_w - sizehints.base_width) / sizehints.width_inc;
1399 window_w = window_w * sizehints.width_inc + sizehints.base_width;
1400 }
1401 if (window_h > 0)
1402 {
1403 window_h = (window_h - sizehints.base_height) / sizehints.height_inc;
1404 window_h = window_h * sizehints.height_inc + sizehints.base_height;
1405 }
1406 desk_w = (window_w - Columns + 1) / Columns;
1407 desk_h = (window_h - Rows * label_h - Rows + 1) / Rows;
1408 w = (desk_w - n)/(n+1);
1409 h = (desk_h - m)/(m+1);
1410
1411 XSetWMNormalHints(dpy,Scr.Pager_w,&sizehints);
1412
1413 x = (desk_w - n) * Scr.Vx / Scr.VWidth + n1;
1414 y = (desk_h - m) * Scr.Vy / Scr.VHeight + m1;
1415
1416 for(k=0;k<Rows;k++)
1417 {
1418 for(j=0;j<Columns;j++)
1419 {
1420 i = k*Columns+j;
1421 if (i<ndesks)
1422 {
1423 XMoveResizeWindow(
1424 dpy,Desks[i].title_w, (desk_w+1)*j-1,(desk_h+label_h+1)*k-1,
1425 desk_w,desk_h+label_h);
1426 XMoveResizeWindow(
1427 dpy,Desks[i].w, -1, (LabelsBelow) ? -1 : label_h - 1, desk_w,desk_h);
1428 if (!is_size_changed)
1429 {
1430 if (CSET_IS_TRANSPARENT(Desks[i].colorset))
1431 {
1432 draw_desk_background(i, w, h);
1433 }
1434 }
1435 if (HilightDesks)
1436 {
1437 if(i == Scr.CurrentDesk - desk1)
1438 XMoveResizeWindow(dpy, Desks[i].CPagerWin, x,y,w,h);
1439 else
1440 XMoveResizeWindow(dpy, Desks[i].CPagerWin, -32768, -32768,w,h);
1441 }
1442 draw_desk_background(i, w, h);
1443 }
1444 }
1445 }
1446 /* reconfigure all the subordinate windows */
1447 ReConfigureAll();
1448 }
1449
1450 /*
1451 *
1452 * Respond to a "background" change: update the Parental Relative cset
1453 *
1454 */
1455
1456 /* layout:
1457 * Root -> pager window (pr) -> title window -> desk window -> window view
1458 * | |-> hilight desk
1459 * |-> icon_window -> icon view
1460 * |-> ballon window
1461 */
1462
1463 /* update the hilight desk and the windows: desk color change */
1464 static
update_pr_transparent_subwindows(int i)1465 void update_pr_transparent_subwindows(int i)
1466 {
1467 int cset;
1468 int n,m,w,h;
1469 PagerWindow *t;
1470
1471 n = Scr.VxMax / Scr.MyDisplayWidth;
1472 m = Scr.VyMax / Scr.MyDisplayHeight;
1473 w = (desk_w - n)/(n+1);
1474 h = (desk_h - m)/(m+1);
1475
1476 if (CSET_IS_TRANSPARENT_PR(Desks[i].highcolorset) && HilightDesks)
1477 {
1478 SetWindowBackground(
1479 dpy, Desks[i].CPagerWin, w, h,
1480 &Colorset[Desks[i].highcolorset],
1481 Pdepth, Scr.NormalGC, True);
1482 }
1483
1484 t = Start;
1485 for(t = Start; t != NULL; t = t->next)
1486 {
1487 cset = (t != FocusWin) ? windowcolorset : activecolorset;
1488 if (t->desk != i && !CSET_IS_TRANSPARENT_PR(cset))
1489 {
1490 continue;
1491 }
1492 if (t->PagerView != None)
1493 {
1494 SetWindowBackground(
1495 dpy, t->PagerView, t->pager_view_width,
1496 t->pager_view_height,
1497 &Colorset[cset], Pdepth, Scr.NormalGC, True);
1498 }
1499 if (t->IconView)
1500 {
1501 SetWindowBackground(
1502 dpy, t->IconView, t->icon_view_width,
1503 t->icon_view_height,
1504 &Colorset[cset], Pdepth, Scr.NormalGC, True);
1505 }
1506 }
1507 }
1508
1509 /* update all the parental relative windows: pr background change */
update_pr_transparent_windows(void)1510 void update_pr_transparent_windows(void)
1511 {
1512 int i,j,k,cset;
1513 int n,m,w,h;
1514 PagerWindow *t;
1515
1516 n = Scr.VxMax / Scr.MyDisplayWidth;
1517 m = Scr.VyMax / Scr.MyDisplayHeight;
1518 w = (desk_w - n)/(n+1);
1519 h = (desk_h - m)/(m+1);
1520
1521 for(k=0;k<Rows;k++)
1522 {
1523 for(j=0;j<Columns;j++)
1524 {
1525 i = k*Columns+j;
1526 if (i < ndesks)
1527 {
1528 if (CSET_IS_TRANSPARENT_PR(Desks[i].colorset))
1529 {
1530 draw_desk_background(i, w, h);
1531 }
1532 else if (CSET_IS_TRANSPARENT_PR(
1533 Desks[i].highcolorset) && HilightDesks)
1534 {
1535 SetWindowBackground(
1536 dpy, Desks[i].CPagerWin, w, h,
1537 &Colorset[Desks[i].highcolorset],
1538 Pdepth, Scr.NormalGC, True);
1539 }
1540 }
1541 }
1542 }
1543 /* subordinate windows with a pr parent desk */
1544 t = Start;
1545 for(t = Start; t != NULL; t = t->next)
1546 {
1547 cset = (t != FocusWin) ? windowcolorset : activecolorset;
1548 if (!CSET_IS_TRANSPARENT_PR(cset) ||
1549 (fAlwaysCurrentDesk &&
1550 !CSET_IS_TRANSPARENT_PR(Desks[0].colorset)) ||
1551 (!fAlwaysCurrentDesk &&
1552 !CSET_IS_TRANSPARENT_PR(Desks[t->desk].colorset)))
1553 {
1554 continue;
1555 }
1556 if (t->PagerView != None)
1557 {
1558 SetWindowBackground(
1559 dpy, t->PagerView, t->pager_view_width,
1560 t->pager_view_height,
1561 &Colorset[cset], Pdepth, Scr.NormalGC, True);
1562 }
1563 if (t->desk && t->IconView)
1564 {
1565 SetWindowBackground(
1566 dpy, t->IconView, t->icon_view_width,
1567 t->icon_view_height,
1568 &Colorset[cset], Pdepth, Scr.NormalGC, True);
1569 }
1570 }
1571
1572 /* ballon */
1573 if (BalloonView != None)
1574 {
1575 cset = Desks[Scr.balloon_desk].ballooncolorset;
1576 if (CSET_IS_TRANSPARENT_PR(cset))
1577 {
1578 XClearArea(dpy, Scr.balloon_w, 0, 0, 0, 0, True);
1579 }
1580 }
1581 }
1582
MovePage(Bool is_new_desk)1583 void MovePage(Bool is_new_desk)
1584 {
1585 int n1,m1,x,y,n,m,i,w,h;
1586 XTextProperty name;
1587 char str[100],*sptr;
1588 static int icon_desk_shown = -1000;
1589
1590 Wait = 0;
1591 n1 = Scr.Vx/Scr.MyDisplayWidth;
1592 m1 = Scr.Vy/Scr.MyDisplayHeight;
1593 n = Scr.VxMax / Scr.MyDisplayWidth;
1594 m = Scr.VyMax / Scr.MyDisplayHeight;
1595
1596 x = (desk_w - n) * Scr.Vx / Scr.VWidth + n1;
1597 y = (desk_h - m) * Scr.Vy / Scr.VHeight + m1;
1598 w = (desk_w - n)/(n+1);
1599 h = (desk_h - m)/(m+1);
1600
1601 for(i=0;i<ndesks;i++)
1602 {
1603 if (HilightDesks)
1604 {
1605 if(i == Scr.CurrentDesk - desk1)
1606 {
1607 XMoveWindow(dpy, Desks[i].CPagerWin, x,y);
1608 XLowerWindow(dpy,Desks[i].CPagerWin);
1609 if (CSET_IS_TRANSPARENT(Desks[i].highcolorset))
1610 {
1611 SetWindowBackground(
1612 dpy, Desks[i].CPagerWin, w, h,
1613 &Colorset[Desks[i].highcolorset], Pdepth,
1614 Scr.NormalGC, True);
1615 }
1616 }
1617 else
1618 {
1619 XMoveWindow(dpy, Desks[i].CPagerWin, -32768,-32768);
1620 }
1621 }
1622 }
1623 DrawIconGrid(1);
1624
1625 ReConfigureIcons(!is_new_desk);
1626
1627 if(Scr.CurrentDesk != icon_desk_shown)
1628 {
1629 icon_desk_shown = Scr.CurrentDesk;
1630
1631 if((Scr.CurrentDesk >= desk1)&&(Scr.CurrentDesk <=desk2))
1632 sptr = Desks[Scr.CurrentDesk -desk1].label;
1633 else
1634 {
1635 sprintf(str, "GotoDesk %d", Scr.CurrentDesk);
1636 sptr = &str[0];
1637 }
1638
1639 if (FlocaleTextListToTextProperty(
1640 dpy, &sptr, 1, XStdICCTextStyle, &name) == 0)
1641 {
1642 fprintf(stderr,"%s: cannot allocate window name", MyName);
1643 return;
1644 }
1645 XSetWMIconName(dpy,Scr.Pager_w,&name);
1646 XFree(name.value);
1647 }
1648 }
1649
ReConfigureAll(void)1650 void ReConfigureAll(void)
1651 {
1652 PagerWindow *t;
1653
1654 t = Start;
1655 while(t!= NULL)
1656 {
1657 MoveResizePagerView(t, True);
1658 t = t->next;
1659 }
1660 }
1661
ReConfigureIcons(Bool do_reconfigure_desk_only)1662 void ReConfigureIcons(Bool do_reconfigure_desk_only)
1663 {
1664 PagerWindow *t;
1665 int x, y, w, h;
1666
1667 for (t = Start; t != NULL; t = t->next)
1668 {
1669 if (do_reconfigure_desk_only && t->desk != Scr.CurrentDesk)
1670 continue;
1671 CalcGeom(t, icon_w, icon_h, &x, &y, &w, &h);
1672 t->icon_view_x = x;
1673 t->icon_view_y = y;
1674 t->icon_view_width = w;
1675 t->icon_view_height = h;
1676 if(Scr.CurrentDesk == t->desk)
1677 XMoveResizeWindow(dpy, t->IconView, x, y, w, h);
1678 else
1679 XMoveResizeWindow(dpy, t->IconView, -32768, -32768, w, h);
1680 }
1681 }
1682
1683 /*
1684 *
1685 * Draw grid lines for desk #i
1686 *
1687 */
DrawGrid(int desk,int erase,Window ew,XRectangle * r)1688 void DrawGrid(int desk, int erase, Window ew, XRectangle *r)
1689 {
1690 int y, y1, y2, x, x1, x2,d,w;
1691 char str[15], *ptr;
1692 int cs;
1693 XRectangle bound;
1694 Region region = 0;
1695
1696 if((desk < 0 ) || (desk >= ndesks))
1697 return;
1698
1699 /* desk grid */
1700 if (!ew || ew == Desks[desk].w)
1701 {
1702 x = Scr.MyDisplayWidth;
1703 y1 = 0;
1704 y2 = desk_h;
1705 while (x < Scr.VWidth)
1706 {
1707 x1 = (x * desk_w) / Scr.VWidth;
1708 if (!use_no_separators)
1709 {
1710 XDrawLine(
1711 dpy,Desks[desk].w,Desks[desk].DashedGC,
1712 x1,y1,x1,y2);
1713 }
1714 x += Scr.MyDisplayWidth;
1715 }
1716 y = Scr.MyDisplayHeight;
1717 x1 = 0;
1718 x2 = desk_w;
1719 while(y < Scr.VHeight)
1720 {
1721 y1 = (y * desk_h) / Scr.VHeight;
1722 if (!use_no_separators)
1723 {
1724 XDrawLine(
1725 dpy,Desks[desk].w,Desks[desk].DashedGC,
1726 x1,y1,x2,y1);
1727 }
1728 y += Scr.MyDisplayHeight;
1729 }
1730 }
1731
1732 if (ew && ew != Desks[desk].title_w)
1733 {
1734 return;
1735 }
1736
1737 /* desk label */
1738 if (r)
1739 {
1740 bound.x = r->x;
1741 bound.y = r->y;
1742 bound.width = r->width;
1743 bound.height = r->height;
1744 region = XCreateRegion();
1745 XUnionRectWithRegion (&bound, region, region);
1746 }
1747 else
1748 {
1749 bound.x = 0;
1750 bound.y = (LabelsBelow ? desk_h : 0);
1751 bound.width = desk_w;
1752 bound.height = label_h;
1753 }
1754
1755 if (FftSupport && Ffont->fftf.fftfont != NULL)
1756 {
1757 erase = True;
1758 }
1759 if(((Scr.CurrentDesk - desk1) == desk) && !ShapeLabels)
1760 {
1761 if (uselabel)
1762 {
1763 XFillRectangle(
1764 dpy,Desks[desk].title_w,Desks[desk].HiliteGC,
1765 bound.x, bound.y, bound.width, bound.height);
1766 }
1767 }
1768 else
1769 {
1770 if(uselabel && erase)
1771 {
1772 XClearArea(dpy,Desks[desk].title_w,
1773 bound.x, bound.y, bound.width, bound.height,
1774 False);
1775 }
1776 }
1777
1778 d = desk1+desk;
1779 ptr = Desks[desk].label;
1780 w = FlocaleTextWidth(Ffont,ptr,strlen(ptr));
1781 if( w > desk_w)
1782 {
1783 sprintf(str,"%d",d);
1784 ptr = str;
1785 w = FlocaleTextWidth(Ffont,ptr,strlen(ptr));
1786 }
1787 if((w <= desk_w)&&(uselabel))
1788 {
1789 FwinString->str = ptr;
1790 FwinString->win = Desks[desk].title_w;
1791 if(desk == (Scr.CurrentDesk - desk1))
1792 {
1793 cs = Desks[desk].highcolorset;
1794 FwinString->gc = Desks[desk].rvGC;
1795 }
1796 else
1797 {
1798 cs = Desks[desk].colorset;
1799 FwinString->gc = Desks[desk].NormalGC;
1800 }
1801
1802 FwinString->flags.has_colorset = False;
1803 if (cs >= 0)
1804 {
1805 FwinString->colorset = &Colorset[cs];
1806 FwinString->flags.has_colorset = True;
1807 }
1808 FwinString->x = (desk_w - w)/2;
1809 FwinString->y = (LabelsBelow ?
1810 desk_h + Ffont->ascent + 1 : Ffont->ascent + 1);
1811 if (region)
1812 {
1813 FwinString->flags.has_clip_region = True;
1814 FwinString->clip_region = region;
1815 XSetRegion(dpy, FwinString->gc, region);
1816 }
1817 else
1818 {
1819 FwinString->flags.has_clip_region = False;
1820 }
1821 FlocaleDrawString(dpy, Ffont, FwinString, 0);
1822 if (region)
1823 {
1824 XDestroyRegion(region);
1825 FwinString->flags.has_clip_region = False;
1826 FwinString->clip_region = None;
1827 XSetClipMask(dpy, FwinString->gc, None);
1828 }
1829 }
1830
1831 if (FShapesSupported)
1832 {
1833 UpdateWindowShape ();
1834 }
1835 }
1836
1837
DrawIconGrid(int erase)1838 void DrawIconGrid(int erase)
1839 {
1840 int y, y1, y2, x, x1, x2,w,h,n,m,n1,m1;
1841 int i;
1842
1843 if(erase)
1844 {
1845 int tmp=(Scr.CurrentDesk - desk1);
1846
1847 if ((tmp < 0) || (tmp >= ndesks))
1848 {
1849 if (PixmapBack)
1850 XSetWindowBackgroundPixmap(dpy, icon_win,PixmapBack->picture);
1851 else
1852 XSetWindowBackground(dpy, icon_win, back_pix);
1853 }
1854 else
1855 {
1856 if (Desks[tmp].bgPixmap)
1857 XSetWindowBackgroundPixmap(
1858 dpy, icon_win,Desks[tmp].bgPixmap->picture);
1859 else if (Desks[tmp].Dcolor)
1860 XSetWindowBackground(dpy, icon_win, GetColor(Desks[tmp].Dcolor));
1861 else if (PixmapBack)
1862 XSetWindowBackgroundPixmap(dpy, icon_win, PixmapBack->picture);
1863 else
1864 XSetWindowBackground(dpy, icon_win, back_pix);
1865 }
1866
1867 XClearWindow(dpy,icon_win);
1868 }
1869
1870 x = Scr.MyDisplayWidth;
1871 y1 = 0;
1872 y2 = icon_h;
1873 while(x < Scr.VWidth)
1874 {
1875 x1 = x * icon_w / Scr.VWidth;
1876 if (!use_no_separators)
1877 for(i=0;i<ndesks;i++)
1878 XDrawLine(dpy,icon_win,Desks[i].DashedGC,x1,y1,x1,y2);
1879 x += Scr.MyDisplayWidth;
1880 }
1881
1882 y = Scr.MyDisplayHeight;
1883 x1 = 0;
1884 x2 = icon_w;
1885 while(y < Scr.VHeight)
1886 {
1887 y1 = y * icon_h / Scr.VHeight;
1888 if (!use_no_separators)
1889 for(i=0;i<ndesks;i++)
1890 XDrawLine(dpy,icon_win,Desks[i].DashedGC,x1,y1,x2,y1);
1891 y += Scr.MyDisplayHeight;
1892 }
1893 n1 = Scr.Vx / Scr.MyDisplayWidth;
1894 m1 = Scr.Vy / Scr.MyDisplayHeight;
1895 n = Scr.VxMax / Scr.MyDisplayWidth;
1896 m = Scr.VyMax / Scr.MyDisplayHeight;
1897 w = (icon_w - n) / (n + 1);
1898 h = (icon_h - m) / (m + 1);
1899
1900 x = (icon_w - n) * Scr.Vx / Scr.VWidth + n1;
1901 y = (icon_h - m) * Scr.Vy / Scr.VHeight + m1;
1902
1903 if (HilightDesks)
1904 {
1905 if (HilightPixmap)
1906 {
1907 for(i=0;i<ndesks;i++)
1908 XCopyArea(dpy, HilightPixmap->picture, icon_win, Scr.NormalGC, 0, 0,
1909 w, h, x, y);
1910 }
1911 else
1912 {
1913 for(i=0;i<ndesks;i++)
1914 XFillRectangle (dpy, icon_win, Desks[i].HiliteGC, x, y, w, h);
1915 }
1916 }
1917 }
1918
1919
SwitchToDesk(int Desk)1920 void SwitchToDesk(int Desk)
1921 {
1922 char command[256];
1923
1924 sprintf(command, "GotoDesk 0 %d", Desk + desk1);
1925 SendText(fd,command,0);
1926 }
1927
1928
SwitchToDeskAndPage(int Desk,XEvent * Event)1929 void SwitchToDeskAndPage(int Desk, XEvent *Event)
1930 {
1931 char command[256];
1932
1933 if (Scr.CurrentDesk != (Desk + desk1))
1934 {
1935 int vx, vy;
1936 /* patch to let mouse button 3 change desks and do not cling to a page */
1937 vx = Event->xbutton.x * Scr.VWidth / (desk_w * Scr.MyDisplayWidth);
1938 vy = Event->xbutton.y * Scr.VHeight / (desk_h * Scr.MyDisplayHeight);
1939 Scr.Vx = vx * Scr.MyDisplayWidth;
1940 Scr.Vy = vy * Scr.MyDisplayHeight;
1941 sprintf(command, "GotoDeskAndPage %d %d %d", Desk + desk1, vx, vy);
1942 SendText(fd, command, 0);
1943
1944 }
1945 else
1946 {
1947 int x = Event->xbutton.x * Scr.VWidth / (desk_w * Scr.MyDisplayWidth);
1948 int y = Event->xbutton.y * Scr.VHeight / (desk_h * Scr.MyDisplayHeight);
1949
1950 /* Fix for buggy XFree86 servers that report button release events
1951 * incorrectly when moving fast. Not perfect, but should at least prevent
1952 * that we get a random page. */
1953 if (x < 0)
1954 x = 0;
1955 if (y < 0)
1956 y = 0;
1957 if (x * Scr.MyDisplayWidth > Scr.VxMax)
1958 x = Scr.VxMax / Scr.MyDisplayWidth;
1959 if (y * Scr.MyDisplayHeight > Scr.VyMax)
1960 y = Scr.VyMax / Scr.MyDisplayHeight;
1961 sprintf(command, "GotoPage %d %d", x, y);
1962 SendText(fd, command, 0);
1963 }
1964 Wait = 1;
1965 }
1966
IconSwitchPage(XEvent * Event)1967 void IconSwitchPage(XEvent *Event)
1968 {
1969 char command[34];
1970
1971 sprintf(command,"GotoPage %d %d",
1972 Event->xbutton.x * Scr.VWidth / (icon_w * Scr.MyDisplayWidth),
1973 Event->xbutton.y * Scr.VHeight / (icon_h * Scr.MyDisplayHeight));
1974 SendText(fd, command, 0);
1975 Wait = 1;
1976 }
1977
1978
AddNewWindow(PagerWindow * t)1979 void AddNewWindow(PagerWindow *t)
1980 {
1981 unsigned long valuemask;
1982 XSetWindowAttributes attributes;
1983 int i, x, y, w, h;
1984
1985 i = t->desk - desk1;
1986 CalcGeom(t, desk_w, desk_h, &x, &y, &w, &h);
1987 t->pager_view_x = x;
1988 t->pager_view_y = y;
1989 t->pager_view_width = w;
1990 t->pager_view_height = h;
1991 valuemask = CWBackPixel | CWEventMask;
1992 attributes.background_pixel = t->back;
1993 attributes.event_mask = ExposureMask;
1994
1995 /* ric@giccs.georgetown.edu -- added Enter and Leave events for
1996 popping up balloon window */
1997 attributes.event_mask =
1998 ExposureMask | EnterWindowMask | LeaveWindowMask;
1999
2000 if ((i >= 0) && (i < ndesks))
2001 {
2002 t->PagerView = XCreateWindow(
2003 dpy,Desks[i].w, x, y, w, h, 0, CopyFromParent,
2004 InputOutput, CopyFromParent, valuemask, &attributes);
2005 if (windowcolorset > -1)
2006 {
2007 SetWindowBackground(
2008 dpy, t->PagerView, w, h,
2009 &Colorset[windowcolorset], Pdepth,
2010 Scr.NormalGC, True);
2011 }
2012 if (!UseSkipList || !DO_SKIP_WINDOW_LIST(t))
2013 {
2014 if (IS_ICONIFIED(t))
2015 {
2016 XMoveResizeWindow(
2017 dpy, t->PagerView, -32768, -32768, 1,
2018 1);
2019 }
2020 XMapRaised(dpy, t->PagerView);
2021 }
2022 }
2023 else
2024 {
2025 t->PagerView = None;
2026 }
2027
2028 CalcGeom(t, icon_w, icon_h, &x, &y, &w, &h);
2029 t->icon_view_x = x;
2030 t->icon_view_y = y;
2031 t->icon_view_width = w;
2032 t->icon_view_height = h;
2033 if(Scr.CurrentDesk != t->desk)
2034 {
2035 x = -32768;
2036 y = -32768;
2037 }
2038 t->IconView = XCreateWindow(
2039 dpy,icon_win, x, y, w, h, 0, CopyFromParent, InputOutput,
2040 CopyFromParent, valuemask, &attributes);
2041 if (windowcolorset > -1)
2042 {
2043 SetWindowBackground(
2044 dpy, t->IconView, w, h, &Colorset[windowcolorset],
2045 Pdepth, Scr.NormalGC, True);
2046 }
2047 if(Scr.CurrentDesk == t->desk)
2048 {
2049 XGrabButton(
2050 dpy, 2, AnyModifier, t->IconView, True,
2051 ButtonPressMask | ButtonReleaseMask|ButtonMotionMask,
2052 GrabModeAsync, GrabModeAsync, None, None);
2053 }
2054 if (!UseSkipList || !DO_SKIP_WINDOW_LIST(t))
2055 {
2056 if (IS_ICONIFIED(t))
2057 {
2058 XMoveResizeWindow(
2059 dpy, t->IconView, -32768, -32768, 1,
2060 1);
2061 }
2062 XMapRaised(dpy, t->IconView);
2063 t->myflags.is_mapped = 1;
2064 }
2065 else
2066 {
2067 t->myflags.is_mapped = 0;
2068 }
2069 Hilight(t, False);
2070
2071 return;
2072 }
2073
2074
ChangeDeskForWindow(PagerWindow * t,long newdesk)2075 void ChangeDeskForWindow(PagerWindow *t,long newdesk)
2076 {
2077 int i, x, y, w, h;
2078 Bool size_changed = False;
2079
2080 i = newdesk - desk1;
2081 if(t->PagerView == None)
2082 {
2083 t->desk = newdesk;
2084 XDestroyWindow(dpy,t->IconView);
2085 AddNewWindow( t);
2086 return;
2087 }
2088
2089 CalcGeom(t, desk_w, desk_h, &x, &y, &w, &h);
2090 size_changed = (t->pager_view_width != w || t->pager_view_height != h);
2091 t->pager_view_x = x;
2092 t->pager_view_y = y;
2093 t->pager_view_width = w;
2094 t->pager_view_height = h;
2095
2096 if ((i >= 0) && (i < ndesks))
2097 {
2098 int cset;
2099
2100 XReparentWindow(dpy, t->PagerView, Desks[i].w, x, y);
2101 if (size_changed)
2102 XResizeWindow(dpy, t->PagerView, w, h);
2103 cset = (t != FocusWin) ? windowcolorset : activecolorset;
2104 if (cset > -1 && (size_changed || CSET_IS_TRANSPARENT(cset)))
2105 {
2106 SetWindowBackground(
2107 dpy, t->PagerView, t->pager_view_width, t->pager_view_height,
2108 &Colorset[cset], Pdepth, Scr.NormalGC, True);
2109 }
2110 }
2111 else
2112 {
2113 XDestroyWindow(dpy,t->PagerView);
2114 t->PagerView = None;
2115 }
2116 t->desk = i+desk1;
2117
2118 CalcGeom(t, icon_w, icon_h, &x, &y, &w, &h);
2119 size_changed = (t->icon_view_width != w || t->icon_view_height != h);
2120 t->icon_view_x = x;
2121 t->icon_view_y = y;
2122 t->icon_view_width = w;
2123 t->icon_view_height = h;
2124 if(Scr.CurrentDesk != t->desk)
2125 XMoveResizeWindow(dpy,t->IconView,-32768,-32768,w,h);
2126 else
2127 {
2128 int cset;
2129
2130 XMoveResizeWindow(dpy,t->IconView,x,y,w,h);
2131 cset = (t != FocusWin) ? windowcolorset : activecolorset;
2132 if (cset > -1 && (size_changed || CSET_IS_TRANSPARENT(cset)))
2133 {
2134 SetWindowBackground(
2135 dpy, t->IconView, t->icon_view_width, t->icon_view_height,
2136 &Colorset[cset], Pdepth, Scr.NormalGC, True);
2137 }
2138 }
2139 }
2140
MoveResizePagerView(PagerWindow * t,Bool do_force_redraw)2141 void MoveResizePagerView(PagerWindow *t, Bool do_force_redraw)
2142 {
2143 int x, y, w, h;
2144 Bool size_changed;
2145 Bool position_changed;
2146
2147 if (UseSkipList && DO_SKIP_WINDOW_LIST(t) && t->myflags.is_mapped)
2148 {
2149 if (t->PagerView)
2150 XUnmapWindow(dpy, t->PagerView);
2151 if (t->IconView)
2152 XUnmapWindow(dpy, t->IconView);
2153 t->myflags.is_mapped = 0;
2154 }
2155 else if (UseSkipList && !DO_SKIP_WINDOW_LIST(t) && !t->myflags.is_mapped)
2156 {
2157 if (t->PagerView)
2158 XMapRaised(dpy, t->PagerView);
2159 if (t->IconView)
2160 XMapRaised(dpy, t->IconView);
2161 t->myflags.is_mapped = 1;
2162 }
2163
2164 CalcGeom(t, desk_w, desk_h, &x, &y, &w, &h);
2165 position_changed = (t->pager_view_x != x || t->pager_view_y != y);
2166 size_changed = (t->pager_view_width != w || t->pager_view_height != h);
2167 t->pager_view_x = x;
2168 t->pager_view_y = y;
2169 t->pager_view_width = w;
2170 t->pager_view_height = h;
2171 if (t->PagerView != None)
2172 {
2173 if (size_changed || position_changed || do_force_redraw)
2174 {
2175 int cset;
2176
2177 XMoveResizeWindow(dpy, t->PagerView, x, y, w, h);
2178 cset = (t != FocusWin) ? windowcolorset : activecolorset;
2179 if (cset > -1 && (size_changed || CSET_IS_TRANSPARENT(cset)))
2180 {
2181 SetWindowBackground(
2182 dpy, t->PagerView, t->pager_view_width, t->pager_view_height,
2183 &Colorset[cset], Pdepth, Scr.NormalGC, True);
2184 }
2185 }
2186 }
2187 else if (t->desk >= desk1 && t->desk <= desk2)
2188 {
2189 XDestroyWindow(dpy, t->IconView);
2190 AddNewWindow(t);
2191 return;
2192 }
2193
2194 CalcGeom(t, icon_w, icon_h, &x, &y, &w, &h);
2195 position_changed = (t->icon_view_x != x || t->icon_view_y != y);
2196 size_changed = (t->icon_view_width != w || t->icon_view_height != h);
2197 t->icon_view_x = x;
2198 t->icon_view_y = y;
2199 t->icon_view_width = w;
2200 t->icon_view_height = h;
2201 if (Scr.CurrentDesk == t->desk)
2202 {
2203 int cset;
2204
2205 XMoveResizeWindow(dpy, t->IconView, x, y, w, h);
2206 cset = (t != FocusWin) ? windowcolorset : activecolorset;
2207 if (cset > -1 && (size_changed || CSET_IS_TRANSPARENT(cset)))
2208 {
2209 SetWindowBackground(
2210 dpy, t->IconView, t->icon_view_width, t->icon_view_height,
2211 &Colorset[cset], Pdepth, Scr.NormalGC, True);
2212 }
2213 }
2214 else
2215 {
2216 XMoveResizeWindow(dpy, t->IconView, -32768, -32768, w, h);
2217 }
2218 }
2219
2220
MoveStickyWindow(Bool is_new_page,Bool is_new_desk)2221 void MoveStickyWindow(Bool is_new_page, Bool is_new_desk)
2222 {
2223 PagerWindow *t;
2224
2225 for (t = Start; t != NULL; t = t->next)
2226 {
2227 if (
2228 is_new_desk && t->desk != Scr.CurrentDesk &&
2229 ((IS_ICONIFIED(t) && IS_ICON_STICKY_ACROSS_DESKS(t)) ||
2230 IS_STICKY_ACROSS_DESKS(t)))
2231 {
2232 ChangeDeskForWindow(t, Scr.CurrentDesk);
2233 }
2234 else if (
2235 is_new_page &&
2236 ((IS_ICONIFIED(t) &&
2237 IS_ICON_STICKY_ACROSS_PAGES(t)) ||
2238 IS_STICKY_ACROSS_PAGES(t)))
2239 {
2240 MoveResizePagerView(t, True);
2241 }
2242 }
2243 }
2244
Hilight(PagerWindow * t,int on)2245 void Hilight(PagerWindow *t, int on)
2246 {
2247
2248 if(!t)
2249 return;
2250
2251 if(Pdepth < 2)
2252 {
2253 if(on)
2254 {
2255 if(t->PagerView != None)
2256 XSetWindowBackgroundPixmap(dpy,t->PagerView,Scr.gray_pixmap);
2257 XSetWindowBackgroundPixmap(dpy,t->IconView,Scr.gray_pixmap);
2258 }
2259 else
2260 {
2261 if(IS_STICKY_ACROSS_DESKS(t) || IS_STICKY_ACROSS_PAGES(t))
2262 {
2263 if(t->PagerView != None)
2264 XSetWindowBackgroundPixmap(dpy,t->PagerView,
2265 Scr.sticky_gray_pixmap);
2266 XSetWindowBackgroundPixmap(dpy,t->IconView,
2267 Scr.sticky_gray_pixmap);
2268 }
2269 else
2270 {
2271 if(t->PagerView != None)
2272 XSetWindowBackgroundPixmap(dpy,t->PagerView,
2273 Scr.light_gray_pixmap);
2274 XSetWindowBackgroundPixmap(dpy,t->IconView,
2275 Scr.light_gray_pixmap);
2276 }
2277 }
2278 if(t->PagerView != None)
2279 XClearArea(dpy, t->PagerView, 0, 0, 0, 0, True);
2280 XClearArea(dpy, t->IconView, 0, 0, 0, 0, True);
2281 }
2282 else
2283 {
2284 int cset;
2285 Pixel pix;
2286
2287 cset = (on) ? activecolorset : windowcolorset;
2288 pix = (on) ? focus_pix : t->back;
2289 if (cset < 0)
2290 {
2291 if (t->PagerView != None)
2292 {
2293 XSetWindowBackground(dpy,t->PagerView,pix);
2294 XClearArea(dpy, t->PagerView, 0, 0, 0, 0, True);
2295 }
2296 XSetWindowBackground(dpy,t->IconView,pix);
2297 XClearArea(dpy, t->IconView, 0, 0, 0, 0, True);
2298 }
2299 else
2300 {
2301 if (t->PagerView != None)
2302 {
2303 SetWindowBackground(
2304 dpy, t->PagerView, t->pager_view_width, t->pager_view_height,
2305 &Colorset[cset], Pdepth, Scr.NormalGC, True);
2306 }
2307 SetWindowBackground(
2308 dpy, t->IconView, t->icon_view_width, t->icon_view_height,
2309 &Colorset[cset], Pdepth, Scr.NormalGC, True);
2310 }
2311 }
2312 }
2313
2314 /* Use Desk == -1 to scroll the icon window */
Scroll(int window_w,int window_h,int x,int y,int Desk,Bool do_scroll_icon)2315 void Scroll(int window_w, int window_h, int x, int y, int Desk,
2316 Bool do_scroll_icon)
2317 {
2318 static int last_sx = -999999;
2319 static int last_sy = -999999;
2320 int sx;
2321 int sy;
2322 int adjx,adjy;
2323
2324 /* Desk < 0 means we want to scroll an icon window */
2325 if (Desk >= 0 && Desk + desk1 != Scr.CurrentDesk)
2326 {
2327 return;
2328 }
2329
2330 /* center around mouse */
2331 adjx = (desk_w / (1 + Scr.VxMax / Scr.MyDisplayWidth));
2332 adjy = (desk_h / (1 + Scr.VyMax / Scr.MyDisplayHeight));
2333 x -= adjx/2;
2334 y -= adjy/2;
2335
2336 /* adjust for pointer going out of range */
2337 if (x < 0)
2338 {
2339 x = 0;
2340 }
2341 if (y < 0)
2342 {
2343 y = 0;
2344 }
2345
2346 if (x > window_w-adjx)
2347 {
2348 x = window_w-adjx;
2349 }
2350 if (y > window_h-adjy)
2351 {
2352 y = window_h-adjy;
2353 }
2354
2355 sx = 0;
2356 sy = 0;
2357 if (window_w != 0)
2358 {
2359 sx = (x * Scr.VWidth / window_w - MyVx);
2360 }
2361 if (window_h != 0)
2362 {
2363 sy = (y * Scr.VHeight / window_h - MyVy);
2364 }
2365 MYFPRINTF((stderr,"[scroll]: %d %d %d %d %d %d\n", window_w, window_h,
2366 x, y, sx, sy));
2367 if (sx == 0 && sy == 0)
2368 {
2369 return;
2370 }
2371 if (Wait == 0 || last_sx != sx || last_sy != sy)
2372 {
2373 do_scroll(sx, sy, False, False);
2374
2375 /* Here we need to track the view offset on the desk. */
2376 /* sx/y are are pixels on the screen to scroll. */
2377 /* We don't use Scr.Vx/y since they lag the true position. */
2378 MyVx += sx;
2379 if (MyVx < 0)
2380 {
2381 MyVx = 0;
2382 }
2383 MyVy += sy;
2384
2385 if (MyVy < 0)
2386 {
2387 MyVy = 0;
2388 }
2389 Wait = 1;
2390 }
2391 if (Wait == 0)
2392 {
2393 last_sx = sx;
2394 last_sy = sy;
2395 }
2396
2397 return;
2398 }
2399
MoveWindow(XEvent * Event)2400 void MoveWindow(XEvent *Event)
2401 {
2402 char command[100];
2403 int x1, y1, wx, wy, n, x, y, xi = 0, yi = 0, wx1, wy1, x2, y2;
2404 int finished = 0;
2405 Window dumwin;
2406 PagerWindow *t;
2407 int m, n1, m1;
2408 int NewDesk, KeepMoving = 0;
2409 int moved = 0;
2410 int row, column;
2411 Window JunkRoot, JunkChild;
2412 int JunkX, JunkY;
2413 unsigned JunkMask;
2414 int do_switch_desk_later = 0;
2415
2416 t = Start;
2417 while (t != NULL && t->PagerView != Event->xbutton.subwindow)
2418 {
2419 t = t->next;
2420 }
2421
2422 if (t == NULL)
2423 {
2424 t = Start;
2425 while (t != NULL && t->IconView != Event->xbutton.subwindow)
2426 {
2427 t = t->next;
2428 }
2429 if (t != NULL)
2430 {
2431 IconMoveWindow(Event, t);
2432 return;
2433 }
2434 }
2435
2436 if (t == NULL || !t->allowed_actions.is_movable)
2437 {
2438 return;
2439 }
2440
2441 NewDesk = t->desk - desk1;
2442 if (NewDesk < 0 || NewDesk >= ndesks)
2443 {
2444 return;
2445 }
2446
2447 n = Scr.VxMax / Scr.MyDisplayWidth;
2448 m = Scr.VyMax / Scr.MyDisplayHeight;
2449 n1 = (Scr.Vx + t->x) / Scr.MyDisplayWidth;
2450 m1 = (Scr.Vy + t->y) / Scr.MyDisplayHeight;
2451 wx = (Scr.Vx + t->x) * (desk_w - n) / Scr.VWidth + n1;
2452 wy = (Scr.Vy + t->y) * (desk_h - m) / Scr.VHeight + m1;
2453 wx1 = wx + (desk_w + 1) * (NewDesk % Columns);
2454 wy1 = wy + label_h + (desk_h + label_h + 1) * (NewDesk / Columns);
2455 if (LabelsBelow)
2456 {
2457 wy1 -= label_h;
2458 }
2459
2460 XReparentWindow(dpy, t->PagerView, Scr.Pager_w, wx1, wy1);
2461 XRaiseWindow(dpy, t->PagerView);
2462
2463 XTranslateCoordinates(dpy, Event->xany.window, t->PagerView,
2464 Event->xbutton.x, Event->xbutton.y, &x1, &y1,
2465 &dumwin);
2466 xi = x1;
2467 yi = y1;
2468 while (!finished)
2469 {
2470 FMaskEvent(dpy, ButtonReleaseMask | ButtonMotionMask |
2471 ExposureMask, Event);
2472 if (Event->type == MotionNotify)
2473 {
2474 XTranslateCoordinates(dpy, Event->xany.window,
2475 Scr.Pager_w, Event->xmotion.x,
2476 Event->xmotion.y, &x, &y,
2477 &dumwin);
2478
2479 if (moved == 0)
2480 {
2481 xi = x;
2482 yi = y;
2483 moved = 1;
2484 }
2485 if (x < -5 || y < -5 || x > window_w + 5 ||
2486 y > window_h + 5)
2487 {
2488 KeepMoving = 1;
2489 finished = 1;
2490 }
2491 XMoveWindow(dpy, t->PagerView, x - x1, y - y1);
2492 }
2493 else if (Event->type == ButtonRelease)
2494 {
2495 XTranslateCoordinates(dpy, Event->xany.window,
2496 Scr.Pager_w, Event->xbutton.x,
2497 Event->xbutton.y, &x, &y,
2498 &dumwin);
2499 XMoveWindow(dpy, t->PagerView, x - x1, y - y1);
2500 finished = 1;
2501 }
2502 else if (Event->type == Expose)
2503 {
2504 HandleExpose(Event);
2505 }
2506 }
2507
2508 if (moved)
2509 {
2510 if (abs(x - xi) < MoveThreshold &&
2511 abs(y - yi) < MoveThreshold)
2512 {
2513 moved = 0;
2514 }
2515 }
2516 if (KeepMoving)
2517 {
2518 NewDesk = Scr.CurrentDesk;
2519
2520 if (NewDesk >= desk1 && NewDesk <= desk2)
2521 {
2522 XReparentWindow(dpy, t->PagerView,
2523 Desks[NewDesk-desk1].w, 0, 0);
2524 }
2525 else
2526 {
2527 XDestroyWindow(dpy, t->PagerView);
2528 t->PagerView = None;
2529 }
2530 if (FQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild,
2531 &x, &y, &JunkX, &JunkY, &JunkMask) == False)
2532 {
2533 /* pointer is on a different screen */
2534 x = 0;
2535 y = 0;
2536 }
2537 XUngrabPointer(dpy,CurrentTime);
2538 XSync(dpy,0);
2539
2540 if (NewDesk != t->desk)
2541 {
2542 /* griph: This used to move to NewDesk, but NewDesk
2543 * is current desk, and if fvwm is on another
2544 * desk (due to async operation) we have to move
2545 * the window to it anyway or "Move Pointer" will
2546 * move an invisible window. */
2547
2548 SendText(fd, "Silent MoveToDesk", t->w);
2549 t->desk = NewDesk;
2550 }
2551 SendText(fd, "Silent Raise", t->w);
2552 SendText(fd, "Silent Move Pointer", t->w);
2553 return;
2554 }
2555 else
2556 {
2557 column = x / (desk_w + 1);
2558 if (column >= Columns)
2559 {
2560 column = Columns - 1;
2561 }
2562 if (column < 0)
2563 {
2564 column = 0;
2565 }
2566 row = y / (desk_h + label_h + 1);
2567 if (row >= Rows)
2568 {
2569 row = Rows - 1;
2570 }
2571 if (row < 0)
2572 {
2573 row = 0;
2574 }
2575 NewDesk = column + row * Columns;
2576 while (NewDesk < 0)
2577 {
2578 NewDesk += Columns;
2579 if (NewDesk >= ndesks)
2580 {
2581 NewDesk = 0;
2582 }
2583 }
2584 while (NewDesk >= ndesks)
2585 {
2586 NewDesk -= Columns;
2587 if (NewDesk < 0)
2588 {
2589 NewDesk = ndesks - 1;
2590 }
2591 }
2592 XTranslateCoordinates(dpy, Scr.Pager_w, Desks[NewDesk].w,
2593 x - x1, y - y1, &x2, &y2, &dumwin);
2594
2595 n1 = x2 * Scr.VWidth / (desk_w * Scr.MyDisplayWidth);
2596 m1 = y2 * Scr.VHeight / (desk_h * Scr.MyDisplayHeight);
2597 x = (x2 - n1) * Scr.VWidth / (desk_w - n) - Scr.Vx;
2598 y = (y2 - m1) * Scr.VHeight / (desk_h - m) - Scr.Vy;
2599 /* force onto desk */
2600 if (x + t->frame_width + Scr.Vx < 0 )
2601 {
2602 x = -Scr.Vx - t->frame_width;
2603 }
2604 if (y + t->frame_height + Scr.Vy < 0)
2605 {
2606 y = -Scr.Vy - t->frame_height;
2607 }
2608 if (x + Scr.Vx >= Scr.VWidth)
2609 {
2610 x = Scr.VWidth - Scr.Vx - 1;
2611 }
2612 if (y + Scr.Vy >= Scr.VHeight)
2613 {
2614 y = Scr.VHeight - Scr.Vy - 1;
2615 }
2616 if ((IS_ICONIFIED(t) && IS_ICON_STICKY_ACROSS_DESKS(t)) ||
2617 (IS_STICKY_ACROSS_DESKS(t)))
2618 {
2619 NewDesk = Scr.CurrentDesk - desk1;
2620 if (x > Scr.MyDisplayWidth - 16)
2621 {
2622 x = Scr.MyDisplayWidth - 16;
2623 }
2624 if (y > Scr.MyDisplayHeight - 16)
2625 {
2626 y = Scr.MyDisplayHeight - 16;
2627 }
2628 if (x + t->width < 16)
2629 {
2630 x = 16 - t->width;
2631 }
2632 if (y + t->height < 16)
2633 {
2634 y = 16 - t->height;
2635 }
2636 }
2637 if (NewDesk + desk1 != t->desk)
2638 {
2639 if ((IS_ICONIFIED(t) && IS_ICON_STICKY_ACROSS_DESKS(t))
2640 || (IS_STICKY_ACROSS_DESKS(t)))
2641 {
2642 NewDesk = Scr.CurrentDesk - desk1;
2643 if (t->desk != Scr.CurrentDesk)
2644 {
2645 ChangeDeskForWindow(t,Scr.CurrentDesk);
2646 }
2647 }
2648 else if (NewDesk + desk1 != Scr.CurrentDesk)
2649 {
2650 sprintf(command, "Silent MoveToDesk 0 %d",
2651 NewDesk + desk1);
2652 SendText(fd, command, t->w);
2653 t->desk = NewDesk + desk1;
2654 }
2655 else
2656 {
2657 do_switch_desk_later = 1;
2658 }
2659 }
2660
2661 if (NewDesk >= 0 && NewDesk < ndesks)
2662 {
2663 XReparentWindow(dpy, t->PagerView,
2664 Desks[NewDesk].w, x2, y2);
2665 t->desk = NewDesk;
2666 XClearArea(dpy, t->PagerView, 0, 0, 0, 0, True);
2667 if (moved)
2668 {
2669 char buf[64];
2670 sprintf(buf, "Silent Move +%dp +%dp", x, y);
2671
2672 SendText(fd, buf, t->w);
2673 XSync(dpy,0);
2674 }
2675 else
2676 {
2677 MoveResizePagerView(t, True);
2678 }
2679 SendText(fd, "Silent Raise", t->w);
2680 }
2681 if (do_switch_desk_later)
2682 {
2683 sprintf(command, "Silent MoveToDesk 0 %d", NewDesk +
2684 desk1);
2685 SendText(fd, command, t->w);
2686 t->desk = NewDesk + desk1;
2687 }
2688 if (Scr.CurrentDesk == t->desk)
2689 {
2690 XSync(dpy,0);
2691 usleep(5000);
2692 XSync(dpy,0);
2693
2694 SendText(fd, "Silent FlipFocus NoWarp", t->w);
2695 }
2696 }
2697 if (is_transient)
2698 {
2699 /* does not return */
2700 ExitPager();
2701 }
2702 }
2703
2704
2705 /*
2706 *
2707 * Procedure:
2708 * FvwmErrorHandler - displays info on internal errors
2709 *
2710 */
FvwmErrorHandler(Display * dpy,XErrorEvent * event)2711 int FvwmErrorHandler(Display *dpy, XErrorEvent *event)
2712 {
2713 #if 1
2714 extern Bool error_occured;
2715 error_occured = True;
2716 return 0;
2717 #else
2718 /* really should just exit here... */
2719 /* domivogt (07-mar-1999): No, not really. See comment above. */
2720 PrintXErrorAndCoredump(dpy, event, MyName);
2721 return 0;
2722 #endif /* 1 */
2723 }
2724
draw_window_border(PagerWindow * t,Window w,int width,int height)2725 static void draw_window_border(PagerWindow *t, Window w, int width, int height)
2726 {
2727 if (w != None)
2728 {
2729 if (!WindowBorders3d || windowcolorset < 0 || activecolorset < 0)
2730 {
2731 XSetForeground(dpy, Scr.NormalGC, Scr.black);
2732 RelieveRectangle(
2733 dpy, w, 0, 0, width - 1, t->pager_view_height - 1,
2734 Scr.NormalGC, Scr.NormalGC, WindowBorderWidth);
2735 }
2736 else if (t == FocusWin)
2737 {
2738 RelieveRectangle(
2739 dpy, w, 0, 0, width - 1, height - 1,
2740 Scr.ahGC, Scr.asGC, WindowBorderWidth);
2741 }
2742 else
2743 {
2744 RelieveRectangle(
2745 dpy, w, 0, 0, width - 1, height - 1,
2746 Scr.whGC, Scr.wsGC, WindowBorderWidth);
2747 }
2748 }
2749 }
2750
BorderWindow(PagerWindow * t)2751 void BorderWindow(PagerWindow *t)
2752 {
2753 draw_window_border(
2754 t, t->PagerView, t->pager_view_width, t->pager_view_height);
2755 }
2756
BorderIconWindow(PagerWindow * t)2757 void BorderIconWindow(PagerWindow *t)
2758 {
2759 draw_window_border(
2760 t, t->IconView, t->icon_view_width, t->icon_view_height);
2761 }
2762
2763 /* draw the window label with simple greedy wrapping */
label_window_wrap(PagerWindow * t)2764 static void label_window_wrap(PagerWindow *t)
2765 {
2766 char *cur, *next, *end;
2767 int space_width, cur_width;
2768
2769 space_width = FlocaleTextWidth(FwindowFont, " ", 1);
2770 cur_width = 0;
2771
2772 cur = next = t->window_label;
2773 end = cur + strlen(cur);
2774
2775 while (*cur) {
2776 while (*next) {
2777 int width;
2778 char *p;
2779
2780 if (!(p = strchr(next, ' ')))
2781 p = end;
2782
2783 width = FlocaleTextWidth(FwindowFont, next, p - next );
2784 if (width > t->pager_view_width - cur_width - space_width - 2*label_border)
2785 break;
2786 cur_width += width + space_width;
2787 next = *p ? p + 1 : p;
2788 }
2789
2790 if (cur == next) {
2791 /* word too large for window */
2792 while (*next) {
2793 int len, width;
2794
2795 len = FlocaleStringNumberOfBytes(FwindowFont, next);
2796 width = FlocaleTextWidth(FwindowFont, next, len);
2797
2798 if (width > t->pager_view_width - cur_width - 2*label_border && cur != next)
2799 break;
2800
2801 next += len;
2802 cur_width += width;
2803 }
2804 }
2805
2806 FwinString->str = safemalloc(next - cur + 1);
2807 strncpy(FwinString->str, cur, next - cur);
2808 FwinString->str[next - cur] = 0;
2809
2810 FlocaleDrawString(dpy, FwindowFont, FwinString, 0);
2811
2812 free(FwinString->str);
2813 FwinString->str = NULL;
2814
2815 FwinString->y += FwindowFont->height;
2816 cur = next;
2817 cur_width = 0;
2818 }
2819 }
2820
do_label_window(PagerWindow * t,Window w)2821 static void do_label_window(PagerWindow *t, Window w)
2822 {
2823 int cs;
2824
2825 if (t == FocusWin)
2826 {
2827 XSetForeground(dpy, Scr.NormalGC, focus_fore_pix);
2828 cs = activecolorset;
2829 }
2830 else
2831 {
2832 XSetForeground(dpy, Scr.NormalGC, t->text);
2833 cs = windowcolorset;
2834 }
2835
2836 if (FwindowFont == NULL)
2837 {
2838 return;
2839 }
2840 if (MiniIcons && t->mini_icon.picture && (t->PagerView != None))
2841 {
2842 /* will draw picture instead... */
2843 return;
2844 }
2845 if (t->icon_name == NULL)
2846 {
2847 return;
2848 }
2849
2850 /* Update the window label for this window */
2851 if (t->window_label)
2852 free(t->window_label);
2853 t->window_label = GetBalloonLabel(t, WindowLabelFormat);
2854 if (w != None)
2855 {
2856 if (FftSupport && FwindowFont != NULL && FwindowFont->fftf.fftfont != NULL)
2857 XClearWindow(dpy, w);
2858 FwinString->win = w;
2859 FwinString->gc = Scr.NormalGC;
2860 FwinString->flags.has_colorset = False;
2861 if (cs >= 0)
2862 {
2863 FwinString->colorset = &Colorset[cs];
2864 FwinString->flags.has_colorset = True;
2865 }
2866 FwinString->x = label_border;
2867 FwinString->y = FwindowFont->ascent+2;
2868
2869 label_window_wrap(t);
2870 }
2871 }
2872
LabelWindow(PagerWindow * t)2873 void LabelWindow(PagerWindow *t)
2874 {
2875 do_label_window(t, t->PagerView);
2876 }
2877
LabelIconWindow(PagerWindow * t)2878 void LabelIconWindow(PagerWindow *t)
2879 {
2880 do_label_window(t, t->IconView);
2881 }
2882
do_picture_window(PagerWindow * t,Window w,int width,int height)2883 static void do_picture_window(
2884 PagerWindow *t, Window w, int width, int height)
2885 {
2886 int iconX;
2887 int iconY;
2888 int src_x = 0;
2889 int src_y = 0;
2890 int dest_w, dest_h;
2891 int cs;
2892 FvwmRenderAttributes fra;
2893
2894 if (MiniIcons)
2895 {
2896 if (t->mini_icon.picture && w != None)
2897 {
2898 dest_w = t->mini_icon.width;
2899 dest_h = t->mini_icon.height;
2900 if (width > t->mini_icon.width)
2901 {
2902 iconX = (width - t->mini_icon.width) / 2;
2903 }
2904 else if (width < t->mini_icon.width)
2905 {
2906 iconX = 0;
2907 src_x = (t->mini_icon.width - width) / 2;
2908 dest_w = width;
2909 }
2910 else
2911 {
2912 iconX = 0;
2913 }
2914 if (height > t->mini_icon.height)
2915 {
2916 iconY = (height - t->mini_icon.height) / 2;
2917 }
2918 else if (height < t->mini_icon.height)
2919 {
2920 iconY = 0;
2921 src_y = (t->mini_icon.height - height) / 2;
2922 dest_h = height;
2923 }
2924 else
2925 {
2926 iconY = 0;
2927 }
2928 fra.mask = FRAM_DEST_IS_A_WINDOW;
2929 if (t == FocusWin)
2930 {
2931 cs = activecolorset;
2932 }
2933 else
2934 {
2935 cs = windowcolorset;
2936 }
2937 if (t->mini_icon.alpha != None ||
2938 (cs >= 0 &&
2939 Colorset[cs].icon_alpha_percent < 100))
2940 {
2941 XClearArea(dpy, w, iconX, iconY,
2942 t->mini_icon.width,
2943 t->mini_icon.height, False);
2944 }
2945 if (cs >= 0)
2946 {
2947 fra.mask |= FRAM_HAVE_ICON_CSET;
2948 fra.colorset = &Colorset[cs];
2949 }
2950 PGraphicsRenderPicture(
2951 dpy, w, &t->mini_icon, &fra, w,
2952 Scr.MiniIconGC, None, None, src_x, src_y,
2953 t->mini_icon.width - src_x,
2954 t->mini_icon.height - src_y,
2955 iconX, iconY, dest_w, dest_h, False);
2956 }
2957 }
2958 }
2959
PictureWindow(PagerWindow * t)2960 void PictureWindow (PagerWindow *t)
2961 {
2962 do_picture_window(t, t->PagerView, t->pager_view_width, t->pager_view_height);
2963 }
2964
PictureIconWindow(PagerWindow * t)2965 void PictureIconWindow (PagerWindow *t)
2966 {
2967 do_picture_window(t, t->IconView, t->icon_view_width, t->icon_view_height);
2968 }
2969
IconMoveWindow(XEvent * Event,PagerWindow * t)2970 void IconMoveWindow(XEvent *Event, PagerWindow *t)
2971 {
2972 int x1, y1, finished = 0, n, x = 0, y = 0, xi = 0, yi = 0;
2973 Window dumwin;
2974 int m, n1, m1;
2975 int moved = 0;
2976 int KeepMoving = 0;
2977 Window JunkRoot, JunkChild;
2978 int JunkX, JunkY;
2979 unsigned JunkMask;
2980
2981 if (t == NULL || !t->allowed_actions.is_movable)
2982 {
2983 return;
2984 }
2985
2986 n = Scr.VxMax / Scr.MyDisplayWidth;
2987 m = Scr.VyMax / Scr.MyDisplayHeight;
2988 n1 = (Scr.Vx + t->x) / Scr.MyDisplayWidth;
2989 m1 = (Scr.Vy + t->y) / Scr.MyDisplayHeight;
2990
2991 XRaiseWindow(dpy, t->IconView);
2992
2993 XTranslateCoordinates(dpy, Event->xany.window, t->IconView,
2994 Event->xbutton.x, Event->xbutton.y, &x1, &y1,
2995 &dumwin);
2996 while (!finished)
2997 {
2998 FMaskEvent(dpy, ButtonReleaseMask | ButtonMotionMask |
2999 ExposureMask, Event);
3000
3001 if (Event->type == MotionNotify)
3002 {
3003 x = Event->xbutton.x;
3004 y = Event->xbutton.y;
3005 if (moved == 0)
3006 {
3007 xi = x;
3008 yi = y;
3009 moved = 1;
3010 }
3011
3012 XMoveWindow(dpy, t->IconView, x - x1, y - y1);
3013 if (x < -5 || y < -5 || x > icon_w + 5 ||
3014 y > icon_h + 5)
3015 {
3016 finished = 1;
3017 KeepMoving = 1;
3018 }
3019 }
3020 else if (Event->type == ButtonRelease)
3021 {
3022 x = Event->xbutton.x;
3023 y = Event->xbutton.y;
3024 XMoveWindow(dpy, t->PagerView, x - x1, y - y1);
3025 finished = 1;
3026 }
3027 else if (Event->type == Expose)
3028 {
3029 HandleExpose(Event);
3030 }
3031 }
3032
3033 if (moved)
3034 {
3035 if (abs(x - xi) < MoveThreshold &&
3036 abs(y - yi) < MoveThreshold)
3037 {
3038 moved = 0;
3039 }
3040 }
3041
3042 if (KeepMoving)
3043 {
3044 if (FQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild,
3045 &x, &y, &JunkX, &JunkY, &JunkMask) == False)
3046 {
3047 /* pointer is on a different screen */
3048 x = 0;
3049 y = 0;
3050 }
3051 XUngrabPointer(dpy, CurrentTime);
3052 XSync(dpy, 0);
3053 SendText(fd, "Silent Raise", t->w);
3054 SendText(fd, "Silent Move Pointer", t->w);
3055 }
3056 else
3057 {
3058 x = x - x1;
3059 y = y - y1;
3060 n1 = x * Scr.VWidth / (icon_w * Scr.MyDisplayWidth);
3061 m1 = y * Scr.VHeight / (icon_h * Scr.MyDisplayHeight);
3062 x = (x - n1) * Scr.VWidth / (icon_w - n) - Scr.Vx;
3063 y = (y - m1) * Scr.VHeight / (icon_h - m) - Scr.Vy;
3064 /* force onto desk */
3065 if (x + t->icon_width + Scr.Vx < 0 )
3066 {
3067 x = - Scr.Vx - t->icon_width;
3068 }
3069 if (y + t->icon_height + Scr.Vy < 0)
3070 {
3071 y = - Scr.Vy - t->icon_height;
3072 }
3073 if (x + Scr.Vx >= Scr.VWidth)
3074 {
3075 x = Scr.VWidth - Scr.Vx - 1;
3076 }
3077 if (y + Scr.Vy >= Scr.VHeight)
3078 {
3079 y = Scr.VHeight - Scr.Vy - 1;
3080 }
3081 if ((IS_ICONIFIED(t) && IS_ICON_STICKY_ACROSS_DESKS(t)) ||
3082 IS_STICKY_ACROSS_DESKS(t))
3083 {
3084 if (x > Scr.MyDisplayWidth - 16)
3085 {
3086 x = Scr.MyDisplayWidth - 16;
3087 }
3088 if (y > Scr.MyDisplayHeight - 16)
3089 {
3090 y = Scr.MyDisplayHeight - 16;
3091 }
3092 if (x + t->width < 16)
3093 {
3094 x = 16 - t->width;
3095 }
3096 if (y + t->height < 16)
3097 {
3098 y = 16 - t->height;
3099 }
3100 }
3101 if (moved)
3102 {
3103 char buf[64];
3104 sprintf(buf, "Silent Move +%dp +%dp", x, y);
3105 SendText(fd, buf, t->w);
3106 XSync(dpy, 0);
3107 }
3108 else
3109 {
3110 MoveResizePagerView(t, True);
3111 }
3112 SendText(fd, "Silent Raise", t->w);
3113 SendText(fd, "Silent FlipFocus NoWarp", t->w);
3114 }
3115 if (is_transient)
3116 {
3117 /* does not return */
3118 ExitPager();
3119 }
3120 }
3121
3122
setup_balloon_window(int i)3123 void setup_balloon_window(int i)
3124 {
3125 XSetWindowAttributes xswa;
3126 unsigned long valuemask;
3127
3128 if (!ShowBalloons && Scr.balloon_w == None)
3129 {
3130 return;
3131 }
3132 XUnmapWindow(dpy, Scr.balloon_w);
3133 if (Desks[i].ballooncolorset < 0)
3134 {
3135 xswa.border_pixel = (!BalloonBorderColor) ?
3136 fore_pix : GetColor(BalloonBorderColor);
3137 xswa.background_pixel =
3138 (!BalloonBack) ? back_pix : GetColor(BalloonBack);
3139 valuemask = CWBackPixel | CWBorderPixel;
3140 }
3141 else
3142 {
3143 xswa.border_pixel = Colorset[Desks[i].ballooncolorset].fg;
3144 xswa.background_pixel = Colorset[Desks[i].ballooncolorset].bg;
3145 if (Colorset[Desks[i].ballooncolorset].pixmap)
3146 {
3147 /* set later */
3148 xswa.background_pixmap = None;
3149 valuemask = CWBackPixmap | CWBorderPixel;;
3150 }
3151 else
3152 {
3153 valuemask = CWBackPixel | CWBorderPixel;
3154 }
3155 }
3156 XChangeWindowAttributes(dpy, Scr.balloon_w, valuemask, &xswa);
3157
3158 return;
3159 }
3160
setup_balloon_gc(int i,PagerWindow * t)3161 void setup_balloon_gc(int i, PagerWindow *t)
3162 {
3163 XGCValues xgcv;
3164 unsigned long valuemask;
3165
3166 valuemask = GCForeground;
3167 if (Desks[i].ballooncolorset < 0)
3168 {
3169 xgcv.foreground =
3170 (!BalloonFore) ? fore_pix : GetColor(BalloonFore);
3171 if (BalloonFore == NULL)
3172 {
3173 XSetForeground(dpy, Scr.balloon_gc, t->text);
3174 }
3175 }
3176 else
3177 {
3178 xgcv.foreground = Colorset[Desks[i].ballooncolorset].fg;
3179 }
3180 if (Desks[i].balloon.Ffont->font != NULL)
3181 {
3182 xgcv.font = Desks[i].balloon.Ffont->font->fid;
3183 valuemask |= GCFont;
3184 }
3185 XChangeGC(dpy, Scr.balloon_gc, valuemask, &xgcv);
3186
3187 return;
3188 }
3189
3190 /* Just maps window ... draw stuff in it later after Expose event
3191 -- ric@giccs.georgetown.edu */
MapBalloonWindow(PagerWindow * t,Bool is_icon_view)3192 void MapBalloonWindow(PagerWindow *t, Bool is_icon_view)
3193 {
3194 extern char *BalloonBack;
3195 extern int BalloonYOffset;
3196 extern int BalloonBorderWidth;
3197 Window view, dummy;
3198 int view_width, view_height;
3199 int x, y;
3200 rectangle new_g;
3201 int i;
3202
3203 if (!is_icon_view)
3204 {
3205 view = t->PagerView;
3206 view_width = t->pager_view_width;
3207 view_height = t->pager_view_height;
3208 }
3209 else
3210 {
3211 view = t->IconView;
3212 view_width = t->icon_view_width;
3213 view_height = t->icon_view_height;
3214 }
3215 BalloonView = view;
3216 /* associate balloon with its pager window */
3217 if (fAlwaysCurrentDesk)
3218 {
3219 i = 0;
3220 }
3221 else
3222 {
3223 i = t->desk - desk1;
3224 }
3225
3226 if (i < 0)
3227 return;
3228
3229 Scr.balloon_desk = i;
3230 /* get the label for this balloon */
3231 if (Scr.balloon_label)
3232 {
3233 free(Scr.balloon_label);
3234 }
3235 Scr.balloon_label = GetBalloonLabel(t, BalloonFormatString);
3236 #if 0
3237 if (Scr.balloon_label == NULL)
3238 {
3239 /* dont draw empty labels */
3240 return;
3241 }
3242 #endif
3243 setup_balloon_window(i);
3244 setup_balloon_gc(i, t);
3245 /* calculate window width to accommodate string */
3246 new_g.height = Desks[i].balloon.height;
3247 new_g.width = 4;
3248 if (Scr.balloon_label)
3249 {
3250 new_g.width += FlocaleTextWidth(
3251 Desks[i].balloon.Ffont, Scr.balloon_label,
3252 strlen(Scr.balloon_label));
3253 }
3254 /* get x and y coords relative to pager window */
3255 x = (view_width / 2) - (new_g.width / 2) - BalloonBorderWidth;
3256 if (BalloonYOffset > 0)
3257 {
3258 y = view_height + BalloonYOffset - 1;
3259 }
3260 else
3261 {
3262 y = BalloonYOffset - new_g.height + 1 -
3263 (2 * BalloonBorderWidth);
3264 }
3265 /* balloon is a top-level window, therefore need to
3266 translate pager window coords to root window coords */
3267 XTranslateCoordinates(
3268 dpy, view, Scr.Root, x, y, &new_g.x, &new_g.y,
3269 &dummy);
3270 /* make sure balloon doesn't go off screen
3271 * (actually 2 pixels from edge rather than 0 just to be pretty :-) */
3272 /* too close to top ... make yoffset +ve */
3273 if ( new_g.y < 2 )
3274 {
3275 y = - BalloonYOffset - 1 + view_height;
3276 XTranslateCoordinates(
3277 dpy, view, Scr.Root, x, y, &new_g.x, &new_g.y, &dummy);
3278 }
3279 /* too close to bottom ... make yoffset -ve */
3280 else if ( new_g.y + new_g.height >
3281 Scr.MyDisplayHeight - (2 * BalloonBorderWidth) - 2 )
3282 {
3283 y = - BalloonYOffset + 1 - new_g.height -
3284 (2 * BalloonBorderWidth);
3285 XTranslateCoordinates(
3286 dpy, view, Scr.Root, x, y, &new_g.x, &new_g.y, &dummy);
3287 }
3288 /* too close to left */
3289 if ( new_g.x < 2 )
3290 {
3291 new_g.x = 2;
3292 }
3293 /* too close to right */
3294 else if (new_g.x + new_g.width >
3295 Scr.MyDisplayWidth - (2 * BalloonBorderWidth) - 2 )
3296 {
3297 new_g.x = Scr.MyDisplayWidth - new_g.width -
3298 (2 * BalloonBorderWidth) - 2;
3299 }
3300 /* make changes to window */
3301 XMoveResizeWindow(
3302 dpy, Scr.balloon_w, new_g.x, new_g.y, new_g.width,
3303 new_g.height);
3304 /* if background not set in config make it match pager window */
3305 if ( BalloonBack == NULL )
3306 {
3307 XSetWindowBackground(dpy, Scr.balloon_w, t->back);
3308 }
3309 if (Desks[i].ballooncolorset > -1)
3310 {
3311 SetWindowBackground(
3312 dpy, Scr.balloon_w, new_g.width, new_g.height,
3313 &Colorset[Desks[i].ballooncolorset], Pdepth,
3314 Scr.NormalGC, True);
3315 XSetWindowBorder(
3316 dpy, Scr.balloon_w,
3317 Colorset[Desks[i].ballooncolorset].fg);
3318 }
3319 XMapRaised(dpy, Scr.balloon_w);
3320
3321 return;
3322 }
3323
3324
InsertExpand(char ** dest,char * s)3325 static void InsertExpand(char **dest, char *s)
3326 {
3327 int len;
3328 char *tmp = *dest;
3329
3330 if (!s || !*s)
3331 return;
3332 len = strlen(*dest) + strlen(s) + 1;
3333 *dest = (char *)safemalloc(len);
3334 strcpy(*dest, tmp);
3335 free(tmp);
3336 strcat(*dest, s);
3337 return;
3338 }
3339
3340
3341 /* Generate the BallonLabel from the format string
3342 -- disching@fmi.uni-passau.de */
GetBalloonLabel(const PagerWindow * pw,const char * fmt)3343 char *GetBalloonLabel(const PagerWindow *pw,const char *fmt)
3344 {
3345 char *dest = safestrdup("");
3346 const char *pos = fmt;
3347 char buffer[2];
3348
3349 buffer[1] = '\0';
3350
3351 while (*pos) {
3352 if (*pos=='%' && *(pos+1)!='\0') {
3353 pos++;
3354 switch (*pos) {
3355 case 'i':
3356 InsertExpand(&dest, pw->icon_name);
3357 break;
3358 case 't':
3359 InsertExpand(&dest, pw->window_name);
3360 break;
3361 case 'r':
3362 InsertExpand(&dest, pw->res_name);
3363 break;
3364 case 'c':
3365 InsertExpand(&dest, pw->res_class);
3366 break;
3367 case '%':
3368 buffer[0] = '%';
3369 InsertExpand(&dest, buffer);
3370 break;
3371 default:;
3372 }
3373 } else {
3374 buffer[0] = *pos;
3375 InsertExpand(&dest, buffer);
3376 }
3377 pos++;
3378 }
3379 return dest;
3380 }
3381
3382
3383 /* -- ric@giccs.georgetown.edu */
UnmapBalloonWindow(void)3384 void UnmapBalloonWindow (void)
3385 {
3386 XUnmapWindow(dpy, Scr.balloon_w);
3387 BalloonView = None;
3388 }
3389
3390
3391 /* Draws string in balloon window -- call after it's received Expose event
3392 -- ric@giccs.georgetown.edu */
DrawInBalloonWindow(int i)3393 void DrawInBalloonWindow (int i)
3394 {
3395 FwinString->str = Scr.balloon_label;
3396 FwinString->win = Scr.balloon_w;
3397 FwinString->gc = Scr.balloon_gc;
3398 if (Desks[i].ballooncolorset >= 0)
3399 {
3400 FwinString->colorset = &Colorset[Desks[i].ballooncolorset];
3401 FwinString->flags.has_colorset = True;
3402 }
3403 else
3404 {
3405 FwinString->flags.has_colorset = False;
3406 }
3407 FwinString->x = 2;
3408 FwinString->y = Desks[i].balloon.Ffont->ascent;
3409 FlocaleDrawString(dpy, Desks[i].balloon.Ffont, FwinString, 0);
3410
3411 return;
3412 }
3413
set_window_colorset_background(PagerWindow * t,colorset_t * csetp)3414 static void set_window_colorset_background(
3415 PagerWindow *t, colorset_t *csetp)
3416 {
3417 if (t->PagerView != None)
3418 {
3419 SetWindowBackground(
3420 dpy, t->PagerView, t->pager_view_width, t->pager_view_height,
3421 csetp, Pdepth, Scr.NormalGC, True);
3422 }
3423 SetWindowBackground(
3424 dpy, t->IconView, t->icon_view_width, t->icon_view_height,
3425 csetp, Pdepth, Scr.NormalGC, True);
3426
3427 return;
3428 }
3429
3430 /* should be in sync with draw_desk_background */
change_colorset(int colorset)3431 void change_colorset(int colorset)
3432 {
3433 int i;
3434 PagerWindow *t;
3435
3436 /* just in case */
3437 if (colorset < 0)
3438 return;
3439
3440 XSetWindowBackgroundPixmap(dpy, Scr.Pager_w, default_pixmap);
3441 for(i=0;i<ndesks;i++)
3442 {
3443 if (Desks[i].highcolorset == colorset)
3444 {
3445 XSetForeground(dpy, Desks[i].HiliteGC,Colorset[colorset].bg);
3446 XSetForeground(dpy, Desks[i].rvGC, Colorset[colorset].fg);
3447 if (HilightDesks)
3448 {
3449 if (uselabel && (i == Scr.CurrentDesk))
3450 {
3451 SetWindowBackground(
3452 dpy, Desks[i].title_w, desk_w, desk_h, &Colorset[colorset], Pdepth,
3453 Scr.NormalGC, True);
3454 }
3455 SetWindowBackground(
3456 dpy, Desks[i].CPagerWin, 0, 0, &Colorset[colorset], Pdepth,
3457 Scr.NormalGC, True);
3458 XLowerWindow(dpy,Desks[i].CPagerWin);
3459 }
3460 }
3461
3462 if (Desks[i].colorset == colorset)
3463 {
3464 XSetWindowBorder(dpy, Desks[i].title_w, Colorset[colorset].fg);
3465 XSetWindowBorder(dpy, Desks[i].w, Colorset[colorset].fg);
3466 XSetForeground(dpy, Desks[i].NormalGC,Colorset[colorset].fg);
3467 XSetForeground(dpy, Desks[i].DashedGC,Colorset[colorset].fg);
3468 if (uselabel)
3469 {
3470 SetWindowBackground(
3471 dpy, Desks[i].title_w, desk_w, desk_h + label_h, &Colorset[colorset],
3472 Pdepth, Scr.NormalGC, True);
3473 }
3474 if (label_h != 0 && uselabel && !LabelsBelow &&
3475 !CSET_IS_TRANSPARENT_PR(Desks[i].colorset))
3476 {
3477 SetWindowBackgroundWithOffset(
3478 dpy, Desks[i].w, 0, -label_h, desk_w, desk_h + label_h,
3479 &Colorset[colorset], Pdepth, Scr.NormalGC, True);
3480 }
3481 else
3482 {
3483 SetWindowBackground(
3484 dpy, Desks[i].w, desk_w, desk_h + label_h,
3485 &Colorset[Desks[i].colorset], Pdepth, Scr.NormalGC, True);
3486 }
3487 update_pr_transparent_subwindows(i);
3488 }
3489 else if (Desks[i].highcolorset == colorset && uselabel)
3490 {
3491 SetWindowBackground(
3492 dpy, Desks[i].title_w, 0, 0, &Colorset[Desks[i].colorset], Pdepth,
3493 Scr.NormalGC, True);
3494 }
3495 }
3496 if (ShowBalloons && Desks[Scr.balloon_desk].ballooncolorset == colorset)
3497 {
3498 XSetWindowBackground(dpy, Scr.balloon_w, Colorset[colorset].fg);
3499 XSetForeground(dpy,Scr.balloon_gc, Colorset[colorset].fg);
3500 XClearArea(dpy, Scr.balloon_w, 0, 0, 0, 0, True);
3501 }
3502
3503 if (windowcolorset == colorset)
3504 {
3505 colorset_t *csetp = &Colorset[colorset];
3506
3507 XSetForeground(dpy, Scr.whGC, csetp->hilite);
3508 XSetForeground(dpy, Scr.wsGC, csetp->shadow);
3509 win_back_pix = csetp->bg;
3510 win_fore_pix = csetp->fg;
3511 win_pix_set = True;
3512 for (t = Start; t != NULL; t = t->next)
3513 {
3514 t->text = Colorset[colorset].fg;
3515 if (t != FocusWin)
3516 {
3517 set_window_colorset_background(t, csetp);
3518 }
3519 }
3520 }
3521 if (activecolorset == colorset)
3522 {
3523 colorset_t *csetp = &Colorset[colorset];
3524
3525 focus_fore_pix = csetp->fg;
3526 XSetForeground(dpy, Scr.ahGC, csetp->hilite);
3527 XSetForeground(dpy, Scr.asGC, csetp->shadow);
3528 win_hi_back_pix = csetp->bg;
3529 win_hi_fore_pix = csetp->fg;
3530 win_hi_pix_set = True;
3531 if (FocusWin)
3532 {
3533 set_window_colorset_background(FocusWin, csetp);
3534 }
3535 }
3536
3537 return;
3538 }
3539