cvsimport
[fvwm.git] / modules / FvwmIconBox / FvwmIconBox.c
blobb1451b5c5f7631c51934e8e48d6c71cf4c7c4bd5
1 /* -*-c-*- */
2 /* FvwmIconBox Module --- Copyright 1994, 1995 Nobutaka Suzuki.
4 * No guarantees or warantees or anything are provided or implied in
5 * any way whatsoever. Use this program at your own risk. Permission
6 * to use this program for any purpose is given, as long as the
7 * copyright is kept intact.
9 * The functions based on part of GoodStuff, FvwmScroll, FvwmWinList
10 * and Fvwm are noted by a small copyright atop that function.
11 * Full original copyright is described in COPYRIGHT.
14 /* This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define NONE 0
30 #define VERTICAL 1
31 #define HORIZONTAL 2
33 #include "config.h"
35 #ifdef HAVE_SYS_BSDTYPES_H
36 #include <sys/bsdtypes.h> /* Saul */
37 #endif
39 #include <stdio.h>
40 #include <signal.h>
41 #include <fcntl.h>
42 #include <sys/wait.h>
43 #include "libs/ftime.h"
45 #include <unistd.h>
46 #include <ctype.h>
47 #include "libs/Module.h"
48 #include "libs/fvwmsignal.h"
50 #include <X11/Xlib.h>
51 #include <X11/Xutil.h>
52 #include <X11/Xproto.h>
53 #include <X11/Xatom.h>
54 #include <X11/Intrinsic.h>
56 #include "libs/defaults.h"
57 #include "libs/fvwmlib.h"
58 #include "libs/FScreen.h"
59 #include "libs/FShape.h"
60 #include "libs/FRender.h"
61 #include "libs/FRenderInit.h"
62 #include "libs/Graphics.h"
63 #include "libs/Parse.h"
64 #include "libs/Strings.h"
65 #include "libs/System.h"
66 #include "libs/XError.h"
68 #include "libs/Colorset.h"
69 #include "fvwm/fvwm.h"
70 #include "libs/PictureGraphics.h"
71 #include "libs/PictureUtils.h"
72 #include "libs/Rectangles.h"
74 #include "FvwmIconBox.h"
76 char *MyName;
78 Display *dpy; /* which display are we talking to */
79 int x_fd;
80 fd_set_size_t fd_width;
82 Window Root;
83 int screen;
85 char *Back = "#5f9ea0";
86 char *Fore = "#82dfe3";
87 char *IconBack = "#cfcfcf";
88 char *IconFore = "black";
89 char *ActIconBack = "white";
90 char *ActIconFore = "black";
91 char *font_string = "fixed";
92 int colorset = -1;
93 int Iconcolorset = -1;
94 int IconHicolorset = -1;
95 Bool UseSkipList = False;
96 Bool Swallowed = False;
97 Window SwallowerWin = False;
98 Bool Shaded = False;
99 Bool SwallowerShaded = False;
101 /* same strings as in misc.c */
102 char NoClass[] = "NoClass";
103 char NoResource[] = "NoResource";
105 Pixel fore_pix, hilite_pix, back_pix, shadow_pix;
106 Pixel icon_fore_pix, icon_back_pix, icon_hilite_pix, icon_shadow_pix;
107 Pixel act_icon_fore_pix, act_icon_back_pix,
108 act_icon_hilite_pix, act_icon_shadow_pix;
110 GC NormalGC,ShadowGC,ReliefGC,IconShadowGC,IconReliefGC;
111 FlocaleFont *Ffont;
112 FlocaleWinString *FwinString;
113 Window main_win;
114 Window holder_win;
115 Window icon_win;
116 Window h_scroll_bar;
117 Window v_scroll_bar;
118 Window l_button, r_button, t_button, b_button;
119 Window Pressed = None;
121 long CurrentDesk;
123 int Width, Height;
124 int UWidth, UHeight;
126 #define MW_EVENTS (KeyPressMask| ExposureMask | StructureNotifyMask|\
127 ButtonReleaseMask | ButtonPressMask )
128 #define SCROLL_EVENTS (ExposureMask | StructureNotifyMask|\
129 ButtonReleaseMask |ButtonPressMask | PointerMotionMask)
130 #define BUTTON_EVENTS (ExposureMask | StructureNotifyMask|\
131 ButtonReleaseMask | ButtonPressMask |\
132 LeaveWindowMask | PointerMotionMask)
134 unsigned long m_mask = M_CONFIGURE_WINDOW|M_ADD_WINDOW|M_DESTROY_WINDOW|
135 M_END_WINDOWLIST| M_ICONIFY|M_DEICONIFY|
136 M_RES_NAME|M_RES_CLASS|M_VISIBLE_NAME|M_ICON_FILE|
137 M_DEFAULTICON|M_CONFIG_INFO|M_END_CONFIG_INFO;
138 unsigned long mx_mask = MX_VISIBLE_ICON_NAME|MX_PROPERTY_CHANGE;
140 struct icon_info *Hilite;
141 int main_width, main_height;
142 int num_icons = 0;
143 int num_rows = 1;
144 int num_columns = 6;
145 int Lines = 6;
146 int max_icon_width = 48,max_icon_height = 48;
147 int ButtonWidth,ButtonHeight;
148 int geom_x = -100000, geom_y = -100000;
149 int gravity = NorthWestGravity;
150 int icon_win_x = 0, icon_win_y = 0, icon_win_width = 100,
151 icon_win_height = 100;
152 int interval = 8;
153 int motion = NONE;
154 int primary = LEFT, secondary = BOTTOM;
155 int xneg = 0, yneg = 0;
156 int ClickTime = DEFAULT_CLICKTIME;
157 unsigned int bar_width = 9;
158 int redraw_flag = 3;
159 int icon_relief = 4;
160 int margin1 = 8;
161 int margin2 = 6;
163 /* true if iconified windows doesn't have () around the title */
164 Bool iconified_has_normal_title = False;
166 int normal_title_relief = 2;
167 int iconified_title_relief = 2;
169 Bool normal_title_inverted_relief = False;
170 Bool iconified_title_inverted_relief = False;
172 Pixmap IconwinPixmap = None;
173 char *IconwinPixmapFile = NULL;
175 int h_margin;
176 int v_margin;
178 int fd[2];
180 struct icon_info *Head = NULL;
181 struct icon_info *Tail = NULL;
182 struct iconfile *IconListHead = NULL;
183 struct iconfile *IconListTail = NULL;
184 struct iconfile *DefaultIcon = NULL;
185 struct mousefunc *MouseActions = NULL;
186 struct keyfunc *KeyActions = NULL;
187 char *imagePath = NULL;
188 char *FvwmDefaultIcon = NULL;
190 static Atom wm_del_win;
191 Atom _XA_WM_PROTOCOLS;
192 Atom _XA_WM_NAME;
194 int ready = 0;
195 unsigned long local_flags = 0;
196 int sortby = UNSORT;
198 char* AnimCommand = NULL;
200 static Bool have_double_click = False;
201 static Bool is_dead_pipe = False;
203 static RETSIGTYPE TerminateHandler(int);
204 static int myErrorHandler(Display *dpy, XErrorEvent *event);
205 static void CleanUp(void);
206 static void change_colorset(int color);
208 Bool do_allow_bad_access = False;
209 Bool was_bad_access = False;
212 Main
213 Based on main() from GoodStuff:
214 Copyright 1993, Robert Nation.
216 int main(int argc, char **argv)
218 char *display_name = NULL;
219 char *temp, *s;
220 XIconSize* size;
222 FlocaleInit(LC_CTYPE, "", "", "FvwmIconBox");
224 temp = argv[0];
225 s=strrchr(argv[0], '/');
226 if (s != NULL)
227 temp = s + 1;
229 if((argc != 6)&&(argc != 7)) {
230 fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",temp,
231 VERSION);
232 exit(1);
235 /* aliases support */
236 if (argc == 7 && argv[6] != NULL)
238 MyName = safemalloc(strlen(argv[6])+1);
239 strcpy(MyName, argv[6]);
241 else
243 MyName = safemalloc(strlen(temp)+1);
244 strcpy(MyName, temp);
247 #ifdef HAVE_SIGACTION
249 struct sigaction sigact;
251 #ifdef SA_INTERRUPT
252 sigact.sa_flags = SA_INTERRUPT;
253 #else
254 sigact.sa_flags = 0;
255 #endif
256 sigemptyset(&sigact.sa_mask);
257 sigaddset(&sigact.sa_mask, SIGPIPE);
258 sigaddset(&sigact.sa_mask, SIGTERM);
259 sigaddset(&sigact.sa_mask, SIGINT);
260 sigact.sa_handler = TerminateHandler;
262 sigaction(SIGPIPE, &sigact, NULL);
263 sigaction(SIGTERM, &sigact, NULL);
264 sigaction(SIGINT, &sigact, NULL);
266 #else
268 * No sigaction, so fall back onto standard and unreliable signals
270 #ifdef USE_BSD_SIGNALS
271 fvwmSetSignalMask( sigmask(SIGPIPE) | sigmask(SIGTERM) | sigmask(SIGINT) );
272 #endif
274 signal(SIGPIPE, TerminateHandler);
275 signal(SIGTERM, TerminateHandler);
276 signal(SIGINT, TerminateHandler);
277 #ifdef HAVE_SIGINTERRUPT
278 siginterrupt(SIGPIPE, 1);
279 siginterrupt(SIGTERM, 1);
280 siginterrupt(SIGINT, 1);
281 #endif
282 #endif
284 fd[0] = atoi(argv[1]);
285 fd[1] = atoi(argv[2]);
287 if (!(dpy = XOpenDisplay(display_name)))
289 fprintf(stderr,"%s: can't open display %s", MyName,
290 XDisplayName(display_name));
291 exit (1);
293 flib_init_graphics(dpy);
295 x_fd = XConnectionNumber(dpy);
297 fd_width = GetFdWidth();
299 screen= DefaultScreen(dpy);
300 Root = RootWindow(dpy, screen);
301 if(Root == None)
303 fprintf(stderr,"%s: Screen %d is not valid ", MyName, screen);
304 exit(1);
307 XSetErrorHandler(myErrorHandler);
309 ParseOptions();
310 /* m_mask/mx_mask may have changed in the ParseOptions call*/
311 SetMessageMask(fd, m_mask);
312 SetMessageMask(fd, mx_mask);
314 if ((local_flags & SETWMICONSIZE) && (size = XAllocIconSize()) != NULL){
315 size->max_width = size->min_width = max_icon_width + icon_relief;
316 /* max_height should be >0 */
317 size->max_height = size->min_height = max(1, max_icon_height) + icon_relief;
318 size->width_inc = size->height_inc = 0;
319 XSetIconSizes(dpy, Root, size, 1);
320 XFree(size);
323 CreateWindow();
325 SendText(fd,"Send_WindowList",0);
326 atexit(CleanUp);
328 /* tell fvwm we're running */
329 SendFinishedStartupNotification(fd);
331 /* Lock on send only for iconify and deiconify (for NoIconAction) */
332 SetSyncMask(fd, M_DEICONIFY | M_ICONIFY);
333 SetNoGrabMask(fd, M_DEICONIFY | M_ICONIFY);
335 Loop();
336 return 0;
342 Loop
343 Based on Loop() from GoodStuff:
344 Copyright 1993, Robert Nation.
346 void Loop(void)
348 Window root;
349 struct icon_info *tmp, *exhilite;
350 int x, y, border_width, depth, i;
351 XEvent Event;
352 int tw, th;
353 int diffx, diffy;
354 int oldw, oldh;
355 int ex, ey, ex2, ey2;
357 while( !isTerminated )
359 if(My_XNextEvent(dpy,&Event))
361 switch(Event.type)
363 case Expose:
364 ex = Event.xexpose.x;
365 ey = Event.xexpose.y;
366 ex2 = Event.xexpose.x + Event.xexpose.width;
367 ey2 = Event.xexpose.y + Event.xexpose.height;
368 while (FCheckTypedWindowEvent(
369 dpy, Event.xany.window, Expose, &Event))
371 ex = min(ex, Event.xexpose.x);
372 ey = min(ey, Event.xexpose.y);
373 ex2 = max(ex2, Event.xexpose.x + Event.xexpose.width);
374 ey2 = max(ey2 , Event.xexpose.y + Event.xexpose.height);
376 Event.xexpose.x = ex;
377 Event.xexpose.y = ey;
378 Event.xexpose.width = ex2 - ex;
379 Event.xexpose.height = ey2 - ey;
380 if (Event.xany.window == main_win)
382 RedrawWindow(&Event);
384 else
386 tmp = Head;
387 while(tmp != NULL)
389 if (Event.xany.window == tmp->icon_pixmap_w)
391 RedrawIcon(tmp, 1, &Event);
392 break;
394 else if (Event.xany.window == tmp->IconWin)
396 RedrawIcon(tmp, 2, &Event);
397 break;
399 tmp = tmp->next;
402 break;
404 case ConfigureNotify:
405 if (Event.xconfigure.window == icon_win &&
406 !CSET_IS_TRANSPARENT(colorset))
408 /* needs this event for transparency */
409 break;
411 if (!XGetGeometry(dpy,main_win,&root,&x,&y,
412 (unsigned int *)&tw,(unsigned int *)&th,
413 (unsigned int *)&border_width,
414 (unsigned int *)&depth))
416 break;
418 if (ready && (tw != main_width || th != main_height)){
419 main_width = tw;
420 main_height= th;
421 oldw = Width;
422 oldh = Height;
423 num_columns = (tw - h_margin - interval + 1) / UWidth;
424 num_rows = (th - v_margin - interval + 1) / UHeight;
425 Width = UWidth * num_columns + interval - 1;
426 Height = UHeight * num_rows + interval -1;
427 XMoveResizeWindow(dpy, holder_win, margin1+2,
428 margin1+2,
429 tw - h_margin, th - v_margin);
430 if (!(local_flags & HIDE_H))
431 XResizeWindow(dpy, h_scroll_bar,
432 Width - bar_width*2, bar_width);
433 if (!(local_flags & HIDE_V))
434 XResizeWindow(dpy ,v_scroll_bar,
435 bar_width, Height - bar_width*2);
436 GetIconwinSize(&diffx, &diffy);
437 if (primary == BOTTOM || secondary == BOTTOM)
438 icon_win_y -= Height - oldh;
439 if (primary == RIGHT || secondary == RIGHT)
440 icon_win_x -= Width - oldw;
441 if (icon_win_x < 0)
442 icon_win_x = 0;
443 if (icon_win_y < 0)
444 icon_win_y = 0;
445 if (icon_win_x + Width > icon_win_width)
446 icon_win_x = icon_win_width - Width;
447 if (icon_win_y + Height > icon_win_height)
448 icon_win_y = icon_win_height - Height;
449 XMoveResizeWindow(dpy, icon_win, -icon_win_x,
450 -icon_win_y, icon_win_width,
451 icon_win_height);
452 AdjustIconWindows();
453 if (colorset >= 0)
454 change_colorset(colorset);
455 else {
456 XClearWindow(dpy,main_win);
457 RedrawWindow(NULL);
460 else if (ready && CSET_IS_TRANSPARENT(colorset) &&
461 (Event.xconfigure.send_event ||
462 Event.xconfigure.window == icon_win))
464 /* moved */
465 if (!CSET_IS_TRANSPARENT_PR_PURE(colorset))
467 SetWindowBackground(
468 dpy, icon_win, icon_win_width,
469 icon_win_height,
470 &Colorset[(colorset)],
471 Pdepth, NormalGC, False);
472 XClearArea(dpy, icon_win, 0,0,0,0, False);
474 else
476 XClearArea(dpy, icon_win, 0,0,0,0, False);
478 /* RedrawWindow(NULL);*/
480 break;
481 case KeyPress:
482 ExecuteKey(Event);
483 break;
484 case ButtonPress:
485 if (!(local_flags & HIDE_H)){
486 if (Event.xbutton.window == h_scroll_bar)
487 motion = HORIZONTAL;
488 else if (Event.xbutton.window == l_button){
489 Pressed = l_button;
490 RedrawLeftButton(ShadowGC, ReliefGC);
492 else if (Event.xbutton.window == r_button){
493 Pressed = r_button;
494 RedrawRightButton(ShadowGC, ReliefGC);
497 if (!(local_flags & HIDE_V)){
498 if (Event.xbutton.window == v_scroll_bar)
499 motion = VERTICAL;
500 else if (Event.xbutton.window == t_button){
501 Pressed = t_button;
502 RedrawTopButton(ShadowGC, ReliefGC);
504 else if (Event.xbutton.window == b_button){
505 Pressed = b_button;
506 RedrawBottomButton(ShadowGC, ReliefGC);
509 if ((tmp = Search(Event.xbutton.window)) != NULL)
510 ExecuteAction(Event.xbutton.x, Event.xbutton.y, tmp);
511 break;
513 case ButtonRelease:
514 if (!(local_flags & HIDE_H)){
515 if (Event.xbutton.window == h_scroll_bar && motion ==
516 HORIZONTAL)
517 HScroll(Event.xbutton.x * icon_win_width / Width);
518 else if (Event.xbutton.window == l_button && Pressed ==
519 l_button){
520 Pressed = None;
521 RedrawLeftButton(ReliefGC, ShadowGC);
522 HScroll(icon_win_x - UWidth);
524 else if (Event.xbutton.window == r_button && Pressed ==
525 r_button){
526 Pressed = None;
527 RedrawRightButton(ReliefGC, ShadowGC);
528 HScroll(icon_win_x + UWidth);
531 if (!(local_flags & HIDE_V)){
532 if (Event.xbutton.window == v_scroll_bar && motion
533 == VERTICAL)
534 VScroll(Event.xbutton.y * icon_win_height / Height);
535 else if (Event.xbutton.window == t_button && Pressed ==
536 t_button){
537 Pressed = None;
538 RedrawTopButton(ReliefGC, ShadowGC);
539 VScroll(icon_win_y - UHeight);
541 else if (Event.xbutton.window == b_button && Pressed ==
542 b_button){
543 Pressed = None;
544 RedrawBottomButton(ReliefGC, ShadowGC);
545 VScroll(icon_win_y + UHeight);
548 motion = NONE;
549 break;
551 case MotionNotify:
552 if (motion == VERTICAL){
553 VScroll(Event.xbutton.y * icon_win_height / Height);
554 }else if (motion == HORIZONTAL){
555 HScroll(Event.xbutton.x * icon_win_width / Width);
557 break;
558 case EnterNotify:
559 if ((tmp = Search(Event.xcrossing.window)) != NULL)
560 if ((exhilite = Hilite) != tmp){
561 Hilite = tmp;
562 if (exhilite != NULL)
563 RedrawIcon(exhilite, redraw_flag, NULL);
564 RedrawIcon(tmp, redraw_flag, NULL);
566 break;
568 case LeaveNotify:
569 if ((tmp = Search(Event.xcrossing.window)) != NULL &&
570 tmp == Hilite){
571 Hilite = NULL;
572 RedrawIcon(tmp, redraw_flag, NULL);
574 if (!(local_flags & HIDE_H) && Event.xbutton.window ==
575 l_button && Pressed == l_button){
576 Pressed = None;
577 RedrawLeftButton(ReliefGC, ShadowGC);
579 else if (!(local_flags & HIDE_H) && Event.xbutton.window ==
580 r_button && Pressed == r_button){
581 Pressed = None;
582 RedrawRightButton(ReliefGC, ShadowGC);
584 else if (!(local_flags & HIDE_V) && Event.xbutton.window ==
585 t_button && Pressed == t_button){
586 Pressed = None;
587 RedrawTopButton(ReliefGC, ShadowGC);
589 else if (!(local_flags & HIDE_V) && Event.xbutton.window ==
590 b_button && Pressed == b_button){
591 Pressed = None;
592 RedrawBottomButton(ReliefGC, ShadowGC);
594 break;
595 case ClientMessage:
596 if ((Event.xclient.format==32) &&
597 (Event.xclient.data.l[0]==wm_del_win))
598 exit (0);
599 break;
600 case PropertyNotify:
601 switch (Event.xproperty.atom){
602 case XA_WM_HINTS:
603 if (Event.xproperty.state == PropertyDelete)
604 break;
605 tmp = Head;
606 i=0;
607 while(tmp != NULL){
608 if (Event.xproperty.window == tmp->id)
609 break;
610 tmp = tmp->next;
611 ++i;
613 if (tmp == NULL || tmp->wmhints == NULL ||
614 !(tmp->extra_flags & DEFAULTICON))
615 break;
616 if (tmp->wmhints)
617 XFree (tmp->wmhints);
618 tmp->wmhints = XGetWMHints(dpy, tmp->id);
619 if (tmp->wmhints && (tmp->wmhints->flags & IconPixmapHint)){
620 /* turn off "old" shape mask */
621 if (FShapesSupported && tmp->icon_maskPixmap != None)
623 FShapeCombineMask(
624 dpy, tmp->icon_pixmap_w, FShapeBounding, 0, 0, None,
625 FShapeSet);
627 if (tmp->iconPixmap != None)
628 XFreePixmap(dpy, tmp->iconPixmap);
629 GetIconBitmap(tmp);
630 if (FShapesSupported && tmp->icon_maskPixmap != None)
632 int hr;
633 hr =
634 (Pdefault || (tmp->icon_depth == 1) ||
635 IS_PIXMAP_OURS(tmp)) ? icon_relief/2 : 0;
636 /* This XSync is necessary, do not remove */
637 /* without it the icon window will disappear */
638 /* server: Exceed, client Sparc/Solaris 2.6 */
639 /* don't know if this is a server or xlib bug */
640 XSync(dpy, False);
641 FShapeCombineMask(
642 dpy, tmp->icon_pixmap_w, FShapeBounding, hr, hr,
643 tmp->icon_maskPixmap, FShapeSet);
645 AdjustIconWindow(tmp, i);
646 if (max_icon_height != 0)
647 RedrawIcon(tmp, 1, NULL);
649 break;
651 break;
653 default:
654 break;
658 return;
661 void HScroll(int x)
663 int oldx = icon_win_x;
665 if (x + Width > icon_win_width)
666 x = icon_win_width - Width;
667 if (x < 0)
668 x = 0;
669 if (oldx != x){
670 icon_win_x = x;
671 XMoveWindow(dpy,icon_win, -icon_win_x, -icon_win_y);
672 if (!(local_flags & HIDE_H))
673 RedrawHScrollbar();
675 if (CSET_IS_TRANSPARENT_PR_PURE(colorset))
676 XClearWindow(dpy, icon_win);
679 void VScroll(int y)
681 int oldy = icon_win_y;
683 if (y + Height > icon_win_height)
684 y = icon_win_height - Height;
685 if (y < 0)
686 y = 0;
687 if (oldy != y){
688 icon_win_y = y;
689 XMoveWindow(dpy,icon_win, -icon_win_x, -icon_win_y);
690 if (!(local_flags & HIDE_V))
691 RedrawVScrollbar();
693 if (CSET_IS_TRANSPARENT_PR_PURE(colorset))
694 XClearWindow(dpy, icon_win);
697 struct icon_info *Search(Window w)
699 struct icon_info *tmp;
701 tmp = Head;
702 while (tmp != NULL){
703 if (tmp->IconWin == w || tmp->icon_pixmap_w == w)
704 return tmp;
705 tmp = tmp->next;
707 return NULL;
712 * Draw the window
715 void RedrawWindow(XEvent *evp)
717 XEvent dummy;
719 if (!evp)
721 while (FCheckTypedWindowEvent(dpy, main_win, Expose, &dummy));
723 RelieveRectangle(dpy, main_win, margin1, margin1, Width + 3,
724 Height + 3, ShadowGC, ReliefGC, 2);
725 if (!(local_flags & HIDE_H))
726 RelieveRectangle(dpy, main_win, margin1, margin1 + 4 + Height + margin2,
727 Width + 3, bar_width + 3, ShadowGC, ReliefGC, 2);
728 if (!(local_flags & HIDE_V))
729 RelieveRectangle(dpy, main_win, margin1 + 4 + Width + margin2, margin1,
730 bar_width + 3, Height + 3, ShadowGC, ReliefGC, 2);
731 RelieveRectangle(
732 dpy, main_win, 0, 0, Width -1 + h_margin, Height -1 + v_margin,
733 ReliefGC, ShadowGC, 2);
735 /* scroll bar */
736 if (!(local_flags & HIDE_H))
737 RedrawHScrollbar();
738 if (!(local_flags & HIDE_V))
739 RedrawVScrollbar();
741 /* buttons */
742 if (!(local_flags & HIDE_H)){
743 RedrawLeftButton(ReliefGC, ShadowGC);
744 RedrawRightButton(ReliefGC, ShadowGC);
746 if (!(local_flags & HIDE_V)){
747 RedrawTopButton(ReliefGC, ShadowGC);
748 RedrawBottomButton(ReliefGC, ShadowGC);
751 /* icons */
752 if (!evp)
754 RedrawIcons(NULL);
758 void RedrawIcons(XEvent *evp)
760 struct icon_info *tmp;
762 tmp = Head;
763 while(tmp != NULL){
764 if (window_cond(tmp))
765 RedrawIcon(tmp, redraw_flag, evp);
766 tmp = tmp->next;
770 void RedrawIcon(struct icon_info *item, int f, XEvent *evp)
772 int hr, len;
773 int diff, lm ,w, h, tw;
774 int title_relief;
775 char label[256];
776 int cs;
777 XRectangle inter;
778 Region region = None;
780 hr = icon_relief/2;
782 if (Hilite == item)
784 XSetForeground(dpy, NormalGC, act_icon_fore_pix);
785 XSetBackground(dpy, NormalGC, act_icon_back_pix);
786 XSetForeground(dpy, IconReliefGC, act_icon_hilite_pix);
787 XSetForeground(dpy, IconShadowGC, act_icon_shadow_pix);
788 cs = IconHicolorset;
789 if (max_icon_height != 0 && (IS_ICON_OURS(item)))
791 if (FShapesSupported)
793 XSetWindowBackgroundPixmap(
794 dpy,
795 item->icon_pixmap_w,
796 ParentRelative);
798 else
800 XSetWindowBackground(dpy, item->icon_pixmap_w,
801 act_icon_back_pix);
804 XSetWindowBackground(dpy, item->IconWin, act_icon_back_pix);
806 else
808 cs = Iconcolorset;
809 XSetWindowBackground(dpy, item->IconWin, icon_back_pix);
812 /* icon pixmap */
813 if ((f & 1) && (IS_ICON_OURS(item)))
815 if (item->iconPixmap != None && item->icon_pixmap_w != None)
817 Bool do_draw = True;
819 if (evp)
821 if (!frect_get_intersection(
822 evp->xexpose.x, evp->xexpose.y,
823 evp->xexpose.width, evp->xexpose.height,
824 hr, hr, item->icon_w, item->icon_h,
825 &inter))
827 do_draw = False;
830 else
832 inter.x = hr;
833 inter.y = hr;
834 inter.width = item->icon_w;
835 inter.height = item->icon_h;
837 if (do_draw &&
838 (item->icon_depth == 1 || IS_PIXMAP_OURS(item) ||
839 Pdefault))
841 FvwmRenderAttributes fra;
843 fra.mask = FRAM_DEST_IS_A_WINDOW;
844 if (cs >= 0)
846 fra.mask |= FRAM_HAVE_ICON_CSET;
847 fra.colorset = &Colorset[cs];
849 if (item->icon_alphaPixmap != None ||
850 (cs >= 0 &&
851 Colorset[cs].icon_alpha_percent < 100))
853 if (evp)
855 XClearArea(
856 dpy, item->icon_pixmap_w,
857 evp->xexpose.x,
858 evp->xexpose.y,
859 evp->xexpose.width,
860 evp->xexpose.height,
861 False);
863 else
865 XClearWindow(
866 dpy,
867 item->icon_pixmap_w);
870 PGraphicsRenderPixmaps(
871 dpy, item->icon_pixmap_w,
872 item->iconPixmap,
873 item->icon_maskPixmap,
874 item->icon_alphaPixmap,
875 item->icon_depth,
876 &fra,
877 item->icon_pixmap_w,
878 NormalGC, None, None,
879 inter.x - hr, inter.y - hr,
880 inter.width, inter.height,
881 inter.x, inter.y,
882 inter.width, inter.height, False);
884 else if (do_draw)
886 XCopyArea(dpy, item->iconPixmap,
887 item->icon_pixmap_w,
888 DefaultGC(dpy, screen),
889 inter.x - hr, inter.y - hr,
890 inter.width, inter.height,
891 inter.x, inter.y);
895 if (!(IS_ICON_SHAPED(item))
896 && (Pdefault || (item->icon_depth == 1) ||
897 IS_PIXMAP_OURS(item)))
899 if (item->icon_w > 0 && item->icon_h > 0)
900 RelieveRectangle(dpy, item->icon_pixmap_w,
901 0, 0,
902 item->icon_w + icon_relief - 1,
903 item->icon_h + icon_relief - 1,
904 IconReliefGC,
905 IconShadowGC, 2);
906 else
907 RelieveRectangle(dpy, item->icon_pixmap_w,
908 0, 0,
909 max_icon_width + icon_relief - 1,
910 max_icon_height + icon_relief - 1,
911 IconReliefGC,
912 IconShadowGC, 2);
916 /* label */
917 if (f & 2)
919 w = max_icon_width + icon_relief;
920 h = max_icon_height + icon_relief;
922 if (IS_ICONIFIED(item))
924 if( ! iconified_has_normal_title )
925 sprintf(label, "(%s)", item->name);
926 else
927 strcpy(label, item->name);
930 else
932 strcpy(label, item->name);
935 /* calculate the actual relief thickness */
936 title_relief = IS_ICONIFIED(item) ?
937 iconified_title_relief :
938 normal_title_relief;
941 if (evp)
943 inter.x = evp->xexpose.x;
944 inter.y = evp->xexpose.y;
945 inter.width = evp->xexpose.width;
946 inter.height = evp->xexpose.height;
947 region = XCreateRegion();
948 XUnionRectWithRegion (&inter, region, region);
949 FwinString->flags.has_clip_region = True;
950 FwinString->clip_region = region;
952 else
954 FwinString->flags.has_clip_region = False;
956 len = strlen(label);
957 tw = FlocaleTextWidth(Ffont, label, len);
958 diff = max_icon_width + icon_relief - tw;
959 lm = diff/2;
960 lm = lm > 2 + title_relief ? lm : 2 + title_relief;
962 FwinString->str = label;
963 FwinString->win = item->IconWin;
964 FwinString->gc = NormalGC;
965 FwinString->x = lm;
966 FwinString->y = 1 + max(normal_title_relief,
967 iconified_title_relief) +
968 Ffont->ascent;
969 if (cs >= 0)
971 FwinString->colorset = &Colorset[cs];
972 FwinString->flags.has_colorset = True;
974 else
976 FwinString->flags.has_colorset = False;
981 if (Hilite == item)
983 XRaiseWindow(dpy, item->IconWin);
984 XMoveResizeWindow(dpy, item->IconWin,
985 item->x + min(0, (diff - 8))/2,
986 item->y + h,
987 max(tw + 4 + 2 * title_relief, w),
989 2 * max(iconified_title_relief,
990 normal_title_relief) +
991 Ffont->height);
992 if (evp)
994 XClearArea(
995 dpy, item->IconWin,
996 evp->xexpose.x, evp->xexpose.y,
997 evp->xexpose.width, evp->xexpose.height,
998 False);
1000 else
1002 XClearWindow(dpy, item->IconWin);
1004 FlocaleDrawString(dpy, Ffont, FwinString, 0);
1006 if((IS_ICONIFIED(item) &&
1007 !iconified_title_inverted_relief) ||
1008 (!IS_ICONIFIED(item) &&
1009 !normal_title_inverted_relief))
1011 RelieveRectangle(dpy, item->IconWin, 0, 0,
1012 max(tw + 4 + 2 * title_relief,
1014 - 1,
1017 max(iconified_title_relief,
1018 normal_title_relief) +
1019 Ffont->height - 1,
1020 IconReliefGC, IconShadowGC,
1021 title_relief);
1023 else
1025 RelieveRectangle(dpy, item->IconWin, 0, 0,
1026 max(tw + 4 + 2 * title_relief,
1028 - 1,
1031 max(iconified_title_relief,
1032 normal_title_relief) +
1033 Ffont->height - 1,
1034 IconShadowGC, IconReliefGC,
1035 title_relief);
1039 else
1041 XMoveResizeWindow(dpy, item->IconWin,
1042 item->x, item->y + h,
1045 2 * max(iconified_title_relief,
1046 normal_title_relief) +
1047 Ffont->height);
1048 if (evp)
1050 XClearArea(
1051 dpy, item->IconWin,
1052 evp->xexpose.x, evp->xexpose.y,
1053 evp->xexpose.width, evp->xexpose.height,
1054 False);
1056 else
1058 XClearWindow(dpy, item->IconWin);
1060 FlocaleDrawString(dpy, Ffont, FwinString, 0);
1062 if((IS_ICONIFIED(item) &&
1063 !iconified_title_inverted_relief) ||
1064 (!IS_ICONIFIED(item) &&
1065 !normal_title_inverted_relief))
1067 RelieveRectangle(dpy, item->IconWin, 0, 0,
1068 w - 1,
1071 max(iconified_title_relief,
1072 normal_title_relief) +
1073 Ffont->height - 1,
1074 IconReliefGC, IconShadowGC,
1075 title_relief );
1077 else
1079 RelieveRectangle(dpy, item->IconWin, 0, 0,
1080 w - 1,
1083 max(iconified_title_relief,
1084 normal_title_relief) +
1085 Ffont->height - 1,
1086 IconShadowGC, IconReliefGC,
1087 title_relief );
1091 if (region)
1093 XDestroyRegion(region);
1095 FwinString->flags.has_clip_region = False;
1098 if (Hilite == item)
1100 XSetForeground(dpy, NormalGC, icon_fore_pix);
1101 XSetBackground(dpy, NormalGC, icon_back_pix);
1102 XSetForeground(dpy, IconReliefGC, icon_hilite_pix);
1103 XSetForeground(dpy, IconShadowGC, icon_shadow_pix);
1105 if (max_icon_height != 0 && (IS_ICON_OURS(item)) &&
1106 !FShapesSupported)
1108 XSetWindowBackground(dpy, item->icon_pixmap_w,
1109 icon_back_pix);
1111 XSetWindowBackground(dpy, item->IconWin, icon_back_pix);
1115 void animate(struct icon_info *item, unsigned long *body)
1117 if(item && AnimCommand && (AnimCommand[0] != 0))
1119 char string[256];
1120 int abs_x, abs_y;
1121 Window junkw;
1123 /* do not animate if shaded */
1124 if (Swallowed)
1126 if (SwallowerShaded)
1128 return;
1131 else if (Shaded)
1133 return;
1135 /* check to see if the centre of the icon is displayed in the iconbox */
1136 XTranslateCoordinates(dpy, icon_win, main_win, item->x + (item->icon_w/2),
1137 item->y + (item->icon_h/2), &abs_x, &abs_y, &junkw);
1138 if (junkw == None)
1139 return;
1141 /* find out where it is on screen */
1142 XTranslateCoordinates(dpy, icon_win, Root, item->x, item->y, &abs_x, &abs_y,
1143 &junkw);
1144 if (IS_ICONIFIED(item))
1146 sprintf(string, "%s %d %d %d %d %d %d %d %d",
1147 AnimCommand,
1148 (int)body[7], (int)body[8], (int)body[9], (int)body[10],
1149 abs_x, abs_y, item->icon_w, item->icon_h);
1150 } else {
1151 sprintf(string, "%s %d %d %d %d %d %d %d %d",
1152 AnimCommand,
1153 abs_x, abs_y, item->icon_w, item->icon_h,
1154 (int)body[7], (int)body[8], (int)body[9], (int)body[10]);
1156 SendText(fd, string, 0);
1161 * RedrawHScrollbar
1162 * Based on part of Loop() of GrabWindow.c in FvwmScroll:
1163 * Copyright 1994, Robert Nation.
1165 void RedrawHScrollbar(void)
1167 int x,width;
1169 x = (Width - bar_width*2) * icon_win_x / icon_win_width;
1170 width = (Width - bar_width*2) * Width / icon_win_width;
1171 XClearArea(dpy, h_scroll_bar, 0, 0, Width, bar_width,False);
1172 RelieveRectangle(dpy, h_scroll_bar, x, 0, width - 1, bar_width - 1,
1173 ReliefGC, ShadowGC, 2);
1177 * RedrawVScrollbar
1178 * Based on part of Loop() of GrabWindow.c in FvwmScroll:
1179 * Copyright 1994, Robert Nation.
1181 void RedrawVScrollbar(void)
1183 int y, height;
1185 y = (Height - bar_width*2) * icon_win_y / icon_win_height;
1186 height = (Height - bar_width*2)* Height / icon_win_height;
1187 XClearArea(dpy, v_scroll_bar, 0, 0, bar_width, Height,False);
1188 RelieveRectangle(dpy, v_scroll_bar, 0, y, bar_width - 1, height - 1,
1189 ReliefGC, ShadowGC, 2);
1192 void RedrawLeftButton(GC rgc, GC sgc)
1194 XSegment seg[4];
1195 int i=0;
1197 seg[i].x1 = 1; seg[i].y1 = bar_width/2;
1198 seg[i].x2 = bar_width - 2; seg[i++].y2 = 1;
1200 seg[i].x1 = 0; seg[i].y1 = bar_width/2;
1201 seg[i].x2 = bar_width - 1; seg[i++].y2 = 0;
1202 XDrawSegments(dpy, l_button, rgc, seg, i);
1204 i = 0;
1205 seg[i].x1 = 1; seg[i].y1 = bar_width/2;
1206 seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width - 2;
1208 seg[i].x1 = 0; seg[i].y1 = bar_width/2;
1209 seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width - 1;
1211 seg[i].x1 = bar_width - 2; seg[i].y1 = 1;
1212 seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width - 2;
1214 seg[i].x1 = bar_width - 1; seg[i].y1 = 0;
1215 seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width - 1;
1216 XDrawSegments(dpy, l_button, sgc, seg, i);
1219 void RedrawRightButton(GC rgc, GC sgc)
1221 XSegment seg[4];
1222 int i=0;
1224 seg[i].x1 = 1; seg[i].y1 = 1;
1225 seg[i].x2 = 1; seg[i++].y2 = bar_width - 2;
1227 seg[i].x1 = 0; seg[i].y1 = 0;
1228 seg[i].x2 = 0; seg[i++].y2 = bar_width - 1;
1230 seg[i].x1 = 1; seg[i].y1 = 1;
1231 seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width/2;
1233 seg[i].x1 = 0; seg[i].y1 = 0;
1234 seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width/2;
1236 XDrawSegments(dpy, r_button, rgc, seg, i);
1238 i = 0;
1239 seg[i].x1 = 1; seg[i].y1 = bar_width - 2;
1240 seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width/2;
1242 seg[i].x1 = 0; seg[i].y1 = bar_width - 1;
1243 seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width/2;
1244 XDrawSegments(dpy, r_button, sgc, seg, i);
1247 void RedrawTopButton(GC rgc, GC sgc)
1249 XSegment seg[4];
1250 int i=0;
1252 seg[i].x1 = bar_width/2; seg[i].y1 = 1;
1253 seg[i].x2 = 1; seg[i++].y2 = bar_width - 2;
1255 seg[i].x1 = bar_width/2; seg[i].y1 = 0;
1256 seg[i].x2 = 0; seg[i++].y2 = bar_width - 1;
1257 XDrawSegments(dpy, t_button, rgc, seg, i);
1259 i = 0;
1260 seg[i].x1 = bar_width/2; seg[i].y1 = 1;
1261 seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width - 2;
1263 seg[i].x1 = bar_width/2; seg[i].y1 = 0;
1264 seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width - 1;
1266 seg[i].x1 = 1; seg[i].y1 = bar_width - 2;
1267 seg[i].x2 = bar_width - 2; seg[i++].y2 = bar_width - 2;
1269 seg[i].x1 = 0; seg[i].y1 = bar_width - 1;
1270 seg[i].x2 = bar_width - 1; seg[i++].y2 = bar_width - 1;
1271 XDrawSegments(dpy, t_button, sgc, seg, i);
1274 void RedrawBottomButton(GC rgc, GC sgc)
1276 XSegment seg[4];
1277 int i=0;
1279 seg[i].x1 = 1; seg[i].y1 = 1;
1280 seg[i].x2 = bar_width/2; seg[i++].y2 = bar_width - 2;
1282 seg[i].x1 = 0; seg[i].y1 = 0;
1283 seg[i].x2 = bar_width/2; seg[i++].y2 = bar_width - 1;
1285 seg[i].x1 = 1; seg[i].y1 = 1;
1286 seg[i].x2 = bar_width - 2; seg[i++].y2 = 1;
1288 seg[i].x1 = 0; seg[i].y1 = 0;
1289 seg[i].x2 = bar_width - 1; seg[i++].y2 = 0;
1290 XDrawSegments(dpy, b_button, rgc, seg, i);
1292 i = 0;
1293 seg[i].x1 = bar_width - 2; seg[i].y1 = 1;
1294 seg[i].x2 = bar_width/2; seg[i++].y2 = bar_width - 2;
1296 seg[i].x1 = bar_width - 1; seg[i].y1 = 0;
1297 seg[i].x2 = bar_width/2; seg[i++].y2 = bar_width - 1;
1298 XDrawSegments(dpy, b_button, sgc, seg, i);
1302 * CreateWindow --Sizes and creates the window
1303 * Based on CreateWindow() from GoodStuff:
1304 * Copyright 1993, Robert Nation.
1306 void CreateWindow(void)
1308 XGCValues gcv;
1309 unsigned long gcm;
1310 unsigned long mask;
1311 char *list[2];
1312 XSetWindowAttributes attributes;
1313 XSizeHints mysizehints;
1314 XTextProperty name;
1315 XClassHint class_hints;
1316 int wx = 0;
1317 int wy = 0;
1319 h_margin = margin1*2 + bar_width + margin2 + 8;
1320 v_margin = margin1*2 + bar_width + margin2 + 8;
1322 wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False);
1323 _XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
1325 /* load the font */
1326 Ffont = FlocaleLoadFont(dpy, font_string, MyName);
1327 if (Ffont == NULL)
1329 fprintf(stderr,"%s: No fonts available, exiting\n",MyName);
1330 exit(1);
1333 if ((local_flags & HIDE_H))
1334 v_margin -= bar_width + margin2 + 4;
1335 if ((local_flags & HIDE_V))
1336 h_margin -= bar_width + margin2 + 4;
1338 /* calculate the (maximal) width and height of an icon */
1339 UWidth = max_icon_width + icon_relief + interval;
1340 UHeight = Ffont->height + 2 +
1341 2 * max(normal_title_relief,iconified_title_relief) +
1342 max_icon_height + icon_relief + interval;
1343 Width = UWidth * num_columns + interval -1;
1344 Height = UHeight * num_rows + interval -1;
1346 mysizehints.flags = PWinGravity| PResizeInc | PMinSize;
1348 /* subtract one for the right/bottom border */
1349 mysizehints.min_width = UWidth + interval - 1 + h_margin;
1350 main_width = mysizehints.width = Width + h_margin;
1351 mysizehints.min_height = UHeight + interval - 1 + v_margin;
1352 main_height = mysizehints.height = Height + v_margin;
1353 mysizehints.width_inc = UWidth;
1354 mysizehints.height_inc = UHeight;
1356 if (geom_x > -100000)
1358 if (xneg)
1360 wx = DisplayWidth(dpy,screen) + geom_x - mysizehints.width;
1361 gravity = NorthEastGravity;
1363 else
1365 wx = geom_x;
1367 if (yneg)
1369 wy = DisplayHeight(dpy,screen) + geom_y - mysizehints.height;
1370 gravity = SouthWestGravity;
1372 else
1374 wy = geom_y;
1377 if (xneg && yneg)
1379 gravity = SouthEastGravity;
1382 mysizehints.flags |= USPosition;
1383 /* hack to prevent mapping on wrong screen with StartsOnScreen */
1384 FScreenMangleScreenIntoUSPosHints(FSCREEN_XYPOS, &mysizehints);
1387 mysizehints.win_gravity = gravity;
1389 if(Pdepth < 2)
1391 back_pix = icon_back_pix = act_icon_fore_pix = GetColor("white");
1392 fore_pix = icon_fore_pix = act_icon_back_pix = GetColor("black");
1393 hilite_pix = icon_hilite_pix = act_icon_shadow_pix = icon_back_pix;
1394 shadow_pix = icon_shadow_pix = act_icon_hilite_pix = icon_fore_pix;
1396 else
1398 fore_pix = (colorset < 0) ? GetColor(Fore) : Colorset[colorset].fg;
1399 back_pix = (colorset < 0) ? GetColor(Back) : Colorset[colorset].bg;
1400 icon_back_pix = (Iconcolorset < 0) ? GetColor(IconBack)
1401 : Colorset[Iconcolorset].bg;
1402 icon_fore_pix = (Iconcolorset < 0) ? GetColor(IconFore)
1403 : Colorset[Iconcolorset].fg;
1404 icon_hilite_pix = (Iconcolorset < 0) ? GetHilite(icon_back_pix)
1405 : Colorset[Iconcolorset].hilite;
1406 icon_shadow_pix = (Iconcolorset < 0) ? GetShadow(icon_back_pix)
1407 : Colorset[Iconcolorset].shadow;
1408 act_icon_back_pix = (IconHicolorset < 0) ? GetColor(ActIconBack)
1409 : Colorset[IconHicolorset].bg;
1410 act_icon_fore_pix = (IconHicolorset < 0) ? GetColor(ActIconFore)
1411 : Colorset[IconHicolorset].fg;
1412 act_icon_hilite_pix = (IconHicolorset < 0) ? GetHilite(act_icon_back_pix)
1413 : Colorset[IconHicolorset].hilite;
1414 act_icon_shadow_pix = (IconHicolorset < 0) ? GetShadow(act_icon_back_pix)
1415 : Colorset[IconHicolorset].shadow;
1416 hilite_pix = (colorset < 0) ? GetHilite(back_pix)
1417 : Colorset[colorset].hilite;
1418 shadow_pix = (colorset < 0) ? GetShadow(back_pix)
1419 : Colorset[colorset].shadow;
1422 attributes.background_pixel = back_pix;
1423 attributes.border_pixel = 0;
1424 attributes.colormap = Pcmap;
1425 main_win = XCreateWindow(dpy, Root, wx, wy,
1426 mysizehints.width, mysizehints.height, 0, Pdepth,
1427 InputOutput, Pvisual,
1428 CWBackPixel | CWBorderPixel | CWColormap,
1429 &attributes);
1430 XSetWMProtocols(dpy,main_win,&wm_del_win,1);
1431 XSelectInput(dpy,main_win,MW_EVENTS);
1433 /* set normal_hits, wm_hints, and, class_hints */
1434 list[0]=MyName;
1435 list[1]=NULL;
1436 if (XStringListToTextProperty(list,1,&name) == 0)
1438 fprintf(stderr,"%s: cannot allocate window name",MyName);
1439 return;
1441 class_hints.res_name = MyName;
1442 class_hints.res_class = "FvwmIconBox";
1443 XSetWMProperties(dpy,main_win,&name,&name,
1444 NULL,0,&mysizehints,NULL,&class_hints);
1445 XFree(name.value);
1447 mysizehints.width -= h_margin;
1448 mysizehints.height -= v_margin;
1449 holder_win = XCreateSimpleWindow(dpy,main_win,margin1+2,
1450 margin1+2,
1451 mysizehints.width,
1452 mysizehints.height,
1453 0,fore_pix,back_pix);
1455 icon_win = XCreateSimpleWindow(dpy,holder_win,-icon_win_x,-icon_win_y,
1456 icon_win_width,
1457 icon_win_height,
1458 0,fore_pix,back_pix);
1459 /* needed for transparency */
1460 XSelectInput(dpy,icon_win,StructureNotifyMask);
1462 gcm = GCForeground|GCBackground;
1463 gcv.foreground = hilite_pix;
1464 gcv.background = back_pix;
1465 ReliefGC = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv);
1467 gcv.foreground = shadow_pix;
1468 ShadowGC = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv);
1470 gcv.foreground = icon_hilite_pix;
1471 gcv.background = icon_back_pix;
1472 IconReliefGC = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv);
1474 gcv.foreground = icon_shadow_pix;
1475 IconShadowGC = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv);
1477 gcm = GCForeground|GCBackground;
1478 if (Ffont->font != NULL)
1480 gcm |= GCFont;
1481 gcv.font = Ffont->font->fid;
1483 gcv.foreground = icon_fore_pix;
1484 NormalGC = fvwmlib_XCreateGC(dpy, main_win, gcm, &gcv);
1486 /* init our Flocale window string for text drawing */
1487 FlocaleAllocateWinString(&FwinString);
1489 /* icon_win's background */
1490 if (colorset >= 0) {
1491 SetWindowBackground(dpy, icon_win, icon_win_width, icon_win_height,
1492 &Colorset[(colorset)], Pdepth, NormalGC,
1493 True);
1494 SetWindowBackground(dpy, holder_win, mysizehints.width, mysizehints.height,
1495 &Colorset[(colorset)], Pdepth, NormalGC,
1496 True);
1497 SetWindowBackground(dpy, main_win, mysizehints.width, mysizehints.height,
1498 &Colorset[(colorset)], Pdepth, NormalGC,
1499 True);
1500 } else if (GetBackPixmap() == True){
1501 XSetWindowBackgroundPixmap(dpy, icon_win, IconwinPixmap);
1502 /* special thanks to Dave Goldberg <dsg@mitre.org>
1503 for his helpful information */
1504 XFreePixmap(dpy, IconwinPixmap);
1507 /* scroll bars */
1508 mask = CWWinGravity | CWBackPixel;
1509 attributes.background_pixel = back_pix;
1510 if (!(local_flags & HIDE_H)){
1511 attributes.win_gravity = SouthWestGravity;
1512 h_scroll_bar = XCreateWindow(dpy, main_win, margin1 + 2 +
1513 bar_width,
1514 margin1 + 6 + Height + margin2,
1515 Width - bar_width*2, bar_width,
1516 0, CopyFromParent,
1517 InputOutput, CopyFromParent,
1518 mask, &attributes);
1519 XSelectInput(dpy,h_scroll_bar,SCROLL_EVENTS);
1521 if (!(local_flags & HIDE_V))
1523 attributes.win_gravity = NorthEastGravity;
1524 v_scroll_bar = XCreateWindow(dpy ,main_win, margin1 + 6 +
1525 Width + margin2,
1526 margin1 + 2 + bar_width,
1527 bar_width, Height - bar_width*2,
1528 0, CopyFromParent,
1529 InputOutput, CopyFromParent,
1530 mask, &attributes);
1531 XSelectInput(dpy,v_scroll_bar,SCROLL_EVENTS);
1534 /* buttons */
1535 if (!(local_flags & HIDE_H))
1537 attributes.win_gravity = SouthWestGravity;
1538 l_button = XCreateWindow(dpy, main_win, margin1 + 2,
1539 margin1 + 6 + Height + margin2,
1540 bar_width, bar_width,
1541 0, CopyFromParent,
1542 InputOutput, CopyFromParent,
1543 mask, &attributes);
1544 attributes.win_gravity = SouthEastGravity;
1545 r_button = XCreateWindow(dpy, main_win, margin1 + 2 + Width -
1546 bar_width,
1547 margin1 + 6 + Height + margin2,
1548 bar_width, bar_width,
1549 0, CopyFromParent,
1550 InputOutput, CopyFromParent,
1551 mask, &attributes);
1552 XSelectInput(dpy,l_button,BUTTON_EVENTS);
1553 XSelectInput(dpy,r_button,BUTTON_EVENTS);
1555 if (!(local_flags & HIDE_V)){
1556 attributes.win_gravity = NorthEastGravity;
1557 t_button = XCreateWindow(dpy, main_win, margin1 + 6 +
1558 Width + margin2, margin1 + 2,
1559 bar_width, bar_width,
1560 0, CopyFromParent,
1561 InputOutput, CopyFromParent,
1562 mask, &attributes);
1563 attributes.win_gravity = SouthEastGravity;
1564 b_button = XCreateWindow(dpy, main_win, margin1 + 6 +
1565 Width + margin2,
1566 margin1 + 2 + Height - bar_width,
1567 bar_width, bar_width,
1568 0, CopyFromParent,
1570 InputOutput, CopyFromParent,
1571 mask, &attributes);
1572 XSelectInput(dpy,t_button,BUTTON_EVENTS);
1573 XSelectInput(dpy,b_button,BUTTON_EVENTS);
1577 static void change_colorset(int color)
1579 int x, y;
1580 unsigned int bw, w, h, depth;
1581 Window Junkroot;
1582 Bool do_update_icon = False;
1583 Bool do_update_icon_hi = False;
1585 if (color == colorset)
1587 fore_pix = (colorset < 0) ? GetColor(Fore)
1588 : Colorset[colorset].fg;
1589 back_pix = (colorset < 0) ? GetColor(Back)
1590 : Colorset[colorset].bg;
1591 hilite_pix = (colorset < 0) ? GetHilite(back_pix)
1592 : Colorset[colorset].hilite;
1593 shadow_pix = (colorset < 0) ? GetShadow(back_pix)
1594 : Colorset[colorset].shadow;
1595 if (XGetGeometry(dpy, main_win, &Junkroot, &x, &y, &w, &h, &bw, &depth))
1597 SetWindowBackground(
1598 dpy, main_win, w, h, &Colorset[(colorset)], Pdepth, NormalGC, True);
1600 SetWindowBackground(
1601 dpy, icon_win, icon_win_width, icon_win_height, &Colorset[(colorset)],
1602 Pdepth, NormalGC, True);
1603 SetWindowBackground(dpy, holder_win, main_width - h_margin,
1604 main_height - v_margin, &Colorset[(colorset)], Pdepth, NormalGC, True);
1605 XSetWindowBackground(dpy, h_scroll_bar, back_pix);
1606 XSetWindowBackground(dpy, v_scroll_bar, back_pix);
1607 XSetWindowBackground(dpy, l_button, back_pix);
1608 XSetWindowBackground(dpy, r_button, back_pix);
1609 XSetWindowBackground(dpy, t_button, back_pix);
1610 XSetWindowBackground(dpy, b_button, back_pix);
1611 XSetForeground(dpy, ReliefGC, hilite_pix);
1612 XSetBackground(dpy, ReliefGC, back_pix);
1613 XSetForeground(dpy, ShadowGC, shadow_pix);
1614 XSetBackground(dpy, ShadowGC, back_pix);
1615 XClearWindow(dpy, main_win);
1616 XClearWindow(dpy, holder_win);
1617 XClearWindow(dpy, icon_win);
1618 XClearWindow(dpy, h_scroll_bar);
1619 XClearWindow(dpy, v_scroll_bar);
1620 XClearWindow(dpy, l_button);
1621 XClearWindow(dpy, r_button);
1622 XClearWindow(dpy, t_button);
1623 XClearWindow(dpy, b_button);
1625 if (color == Iconcolorset) {
1626 icon_back_pix = (Iconcolorset < 0) ? GetColor(IconBack)
1627 : Colorset[Iconcolorset].bg;
1628 icon_fore_pix = (Iconcolorset < 0) ? GetColor(IconFore)
1629 : Colorset[Iconcolorset].fg;
1630 icon_hilite_pix = (Iconcolorset < 0) ? GetHilite(icon_back_pix)
1631 : Colorset[Iconcolorset].hilite;
1632 icon_shadow_pix = (Iconcolorset < 0) ? GetShadow(icon_back_pix)
1633 : Colorset[Iconcolorset].shadow;
1634 XSetForeground(dpy, IconReliefGC, icon_hilite_pix);
1635 XSetBackground(dpy, IconReliefGC, icon_back_pix);
1636 XSetForeground(dpy, IconShadowGC, icon_shadow_pix);
1637 XSetBackground(dpy, IconShadowGC, icon_back_pix);
1638 XSetForeground(dpy, NormalGC, icon_fore_pix);
1639 XSetBackground(dpy, NormalGC, icon_back_pix);
1640 do_update_icon = True;
1642 if (color == IconHicolorset)
1644 act_icon_back_pix = (IconHicolorset < 0) ? GetColor(ActIconBack)
1645 : Colorset[IconHicolorset].bg;
1646 act_icon_fore_pix = (IconHicolorset < 0) ? GetColor(ActIconFore)
1647 : Colorset[IconHicolorset].fg;
1648 act_icon_hilite_pix = (IconHicolorset < 0) ? GetHilite(act_icon_back_pix)
1649 : Colorset[IconHicolorset].hilite;
1650 act_icon_shadow_pix = (IconHicolorset < 0) ? GetShadow(act_icon_back_pix)
1651 : Colorset[IconHicolorset].shadow;
1652 do_update_icon_hi = True;
1655 if (do_update_icon_hi || do_update_icon)
1657 struct icon_info *tmp;
1659 tmp = Head;
1660 while(tmp != NULL)
1662 if (window_cond(tmp))
1664 if (tmp == Hilite && do_update_icon_hi)
1666 RedrawIcon(tmp,redraw_flag,NULL);
1668 if (tmp != Hilite && do_update_icon)
1670 RedrawIcon(tmp,redraw_flag,NULL);
1673 tmp = tmp->next;
1678 void GetIconwinSize(int *dx, int *dy)
1680 *dx = icon_win_width;
1681 *dy = icon_win_height;
1683 if (primary == LEFT || primary == RIGHT){
1684 icon_win_width = max(Width, UWidth * Lines + interval - 1);
1685 icon_win_height = max(Height, UHeight * (max(0,
1686 (num_icons-1))/Lines
1687 + 1) - 1 + interval);
1688 }else{
1689 icon_win_width = max(Width, UWidth * (max(0,num_icons-1) / Lines +
1690 1) + interval - 1);
1691 icon_win_height = max(Height, UHeight * Lines - 1 + interval);
1693 *dx = icon_win_width - *dx;
1694 *dy = icon_win_height - *dy;
1697 void MySendFvwmPipe(int *fd, char *message, unsigned long window)
1699 long w;
1700 char *hold, *temp, *temp_msg;
1701 hold = message;
1703 while (1)
1705 temp = strchr(hold, ',');
1706 if (temp != NULL)
1708 temp_msg = safemalloc(temp - hold + 1);
1709 strncpy(temp_msg, hold, temp - hold);
1710 temp_msg[temp - hold]='\0';
1711 hold = temp + 1;
1713 else temp_msg = hold;
1715 if (!ExecIconBoxFunction(temp_msg))
1717 write(fd[0], &window, sizeof(unsigned long));
1719 w=strlen(temp_msg);
1720 write(fd[0], &w, sizeof(w));
1721 write(fd[0], temp_msg, w);
1723 /* keep going */
1725 w = 1;
1726 write(fd[0], &w, sizeof(w));
1728 if (temp_msg != hold) free(temp_msg);
1729 else break;
1733 Bool ExecIconBoxFunction(char *msg)
1735 if (strncasecmp(msg, "Next", 4) == 0){
1736 Next();
1737 return True;
1738 }else if (strncasecmp(msg, "Prev", 4) == 0){
1739 Prev();
1740 return True;
1741 }else if (strncasecmp(msg, "Left", 4) == 0){
1742 HScroll(icon_win_x - UWidth);
1743 return True;
1744 }else if (strncasecmp(msg, "Right", 5) == 0){
1745 HScroll(icon_win_x + UWidth);
1746 return True;
1747 }else if (strncasecmp(msg, "Up", 2) == 0){
1748 VScroll(icon_win_y - UHeight);
1749 return True;
1750 }else if (strncasecmp(msg, "Down", 4) == 0){
1751 VScroll(icon_win_y + UHeight);
1752 return True;
1754 return False;
1757 void Next(void)
1759 struct icon_info *new, *old;
1760 int i;
1762 old = new = Hilite;
1764 if (new != NULL)
1765 new = new->next;
1767 if (new != NULL)
1768 Hilite = new;
1769 else
1770 new = Hilite = Head;
1772 if (new == NULL)
1773 return;
1775 if (old != NULL)
1776 RedrawIcon(old, redraw_flag,NULL);
1777 if (new != NULL)
1778 RedrawIcon(new, redraw_flag,NULL);
1780 i=0;
1781 if (new->x < icon_win_x){
1782 while (new->x + UWidth * ++i < icon_win_x)
1784 HScroll(icon_win_x - UWidth*i);
1785 }else if (new->x > icon_win_x + Width){
1786 while (new->x - UWidth * ++i > icon_win_x + Width)
1788 HScroll(icon_win_x + UWidth*i);
1791 i=0;
1792 if (new->y < icon_win_y){
1793 while (new->y + UHeight * ++i < icon_win_y)
1795 VScroll(icon_win_y - UHeight*i);
1796 }else if (new->y > icon_win_y + Height){
1797 while (new->y - UHeight * ++i > icon_win_y + Height)
1799 VScroll(icon_win_y + UHeight*i);
1803 void Prev(void)
1805 struct icon_info *new, *old;
1806 int i;
1808 old = new = Hilite;
1810 if (new != NULL)
1811 new = new->prev;
1813 if (new != NULL)
1814 Hilite = new;
1815 else
1816 new = Hilite = Tail;
1818 if (new == NULL)
1819 return;
1821 if (old != NULL)
1822 RedrawIcon(old, redraw_flag,NULL);
1823 if (new != NULL)
1824 RedrawIcon(new, redraw_flag,NULL);
1826 i=0;
1827 if (new->x < icon_win_x){
1828 while (new->x + UWidth * ++i < icon_win_x)
1830 HScroll(icon_win_x - UWidth*i);
1831 }else if (new->x > icon_win_x + Width){
1832 while (new->x - UWidth * ++i > icon_win_x + Width)
1834 HScroll(icon_win_x + UWidth*i);
1837 i=0;
1838 if (new->y < icon_win_y){
1839 while (new->y + UHeight * ++i < icon_win_y)
1841 VScroll(icon_win_y - UHeight*i);
1842 }else if (new->y > icon_win_y + Height){
1843 while (new->y - UHeight * ++i > icon_win_y + Height)
1845 VScroll(icon_win_y + UHeight*i);
1850 * TerminateHandler - signal handler to make FvwmIconBox exit cleanly
1852 static RETSIGTYPE
1853 TerminateHandler(int sig)
1856 * This function might not return - it could "long-jump"
1857 * right out, so we need to do everything we need to do
1858 * BEFORE we call it ...
1860 fvwmSetTerminate(sig);
1861 SIGNAL_RETURN;
1866 * DeadPipe --Dead pipe handler
1867 * Based on DeadPipe() from GoodStuff:
1868 * Copyright 1993, Robert Nation.
1870 void
1871 DeadPipe(int nonsense)
1873 is_dead_pipe = True;
1874 exit(0);
1875 SIGNAL_RETURN;
1878 static void
1879 CleanUp(void)
1881 struct icon_info *tmpi;
1882 #if 0
1883 struct icon_info *tmpi, *tmpi2;
1884 struct mousefunc *tmpm, *tmpm2;
1885 struct keyfunc *tmpk, *tmpk2;
1886 struct iconfile *tmpf, *tmpf2;
1887 #endif
1889 if (!is_dead_pipe)
1891 if ((local_flags & SETWMICONSIZE))
1893 XDeleteProperty(dpy, Root, XA_WM_ICON_SIZE);
1894 XFlush(dpy);
1897 /* DV: my, what is all this stuff good for? All memory gets freed
1898 * automatically!
1899 * OC: Yes but the icon window must be reparented to the root window */
1900 tmpi = Head;
1901 while(tmpi != NULL)
1903 if (!IS_ICON_OURS(tmpi) && tmpi->icon_pixmap_w &&
1904 tmpi->icon_w != 0)
1906 XSelectInput(dpy, tmpi->icon_pixmap_w, NoEventMask);
1907 XReparentWindow(dpy, tmpi->icon_pixmap_w, Root, 0, 0);
1908 XUnmapWindow(dpy, tmpi->icon_pixmap_w);
1910 tmpi = tmpi->next;
1912 #if 0
1913 if (FvwmDefaultIcon != NULL)
1914 free(FvwmDefaultIcon);
1916 tmpm = MouseActions;
1917 while(tmpm != NULL){
1918 tmpm2 = tmpm;
1919 tmpm = tmpm->next;
1920 free(tmpm2->action);
1921 free(tmpm2);
1924 tmpk = KeyActions;
1925 while(tmpk != NULL){
1926 tmpk2 = tmpk;
1927 tmpk = tmpk->next;
1928 free(tmpk2->action);
1929 free(tmpk2->name);
1930 free(tmpk2);
1933 tmpf = IconListHead;
1934 while(tmpf != NULL){
1935 tmpf2 = tmpf;
1936 tmpf = tmpf->next;
1937 free(tmpf2->name);
1938 free(tmpf2->iconfile);
1939 free(tmpf2);
1942 tmpi = Head;
1943 while(tmpi != NULL){
1944 tmpi2 = tmpi;
1945 tmpi = tmpi->next;
1946 freeitem(tmpi2, 0);
1948 #endif
1950 return;
1955 * ParseOptions
1956 * Based on ParseConfig() from FvwmWinList:
1957 * Copyright 1994, Mike Finger.
1959 void ParseOptions(void)
1961 char *tline= NULL,*tmp;
1962 int Clength;
1964 Clength = strlen(MyName);
1966 InitGetConfigLine(fd,CatString3("*",MyName,0));
1967 GetConfigLine(fd,&tline);
1969 while(tline != NULL)
1971 int g_x, g_y, flags;
1972 unsigned width,height;
1974 if(strlen(&tline[0])>1)
1976 if (strncasecmp(tline,CatString3("*", MyName, "Geometry"),Clength+9)==0)
1978 num_columns = 6;
1979 num_rows = 1;
1980 geom_x = -10000;
1981 geom_y = -10000;
1982 xneg = 0;
1983 yneg = 0;
1984 tmp = &tline[Clength+9];
1985 while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0))
1986 tmp++;
1987 tmp[strlen(tmp)] = 0;
1988 flags = FScreenParseGeometry(tmp,&g_x,&g_y,&width,&height);
1989 if (flags & WidthValue)
1990 num_columns = width;
1991 if (flags & HeightValue)
1992 num_rows = height;
1993 if (flags & XValue)
1994 geom_x = g_x;
1995 if (flags & YValue)
1996 geom_y = g_y;
1997 if (flags & XNegative)
1998 xneg = 1;
1999 if (flags & YNegative)
2000 yneg = 1;
2002 else if (strncasecmp(tline,CatString3(
2003 "*", MyName, "MaxIconSize"),Clength+12)==0)
2005 tmp = &tline[Clength+12];
2006 while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0))
2007 tmp++;
2008 tmp[strlen(tmp)] = 0;
2010 flags = XParseGeometry(tmp,&g_x,&g_y,&width,&height);
2011 if (flags & WidthValue)
2012 max_icon_width = width;
2013 if (flags & HeightValue)
2014 max_icon_height = height;
2015 if (height == 0){
2016 icon_relief = 0;
2017 redraw_flag = 2;
2018 max_icon_width += 4;
2021 else if (strncasecmp(tline, CatString3(
2022 "*", MyName, "NoIconifiedParentheses"),
2023 Clength+23) == 0)
2025 iconified_has_normal_title = True;
2028 else if (strncasecmp(tline, CatString3(
2029 "*", MyName, "NormalTitleRelief"),
2030 Clength+18) == 0)
2032 normal_title_relief = atoi(&tline[Clength+18]);
2035 else if (strncasecmp(tline, CatString3(
2036 "*", MyName, "IconifiedTitleRelief"),
2037 Clength+21) == 0)
2039 iconified_title_relief = atoi(&tline[Clength+21]);
2042 else if (strncasecmp(tline, CatString3(
2043 "*", MyName, "NormalTitleInvertedRelief"),
2044 Clength+26) == 0)
2046 normal_title_inverted_relief = True;
2049 else if (strncasecmp(tline, CatString3(
2050 "*", MyName, "IconifiedTitleInvertedRelief"),
2051 Clength+29) == 0)
2053 iconified_title_inverted_relief = True;
2056 else if (strncasecmp(tline, "Colorset", 8) == 0)
2058 LoadColorset(&tline[8]);
2060 else if (strncasecmp(tline, XINERAMA_CONFIG_STRING,
2061 sizeof(XINERAMA_CONFIG_STRING) - 1) == 0)
2063 FScreenConfigureModule(
2064 tline + sizeof(XINERAMA_CONFIG_STRING) - 1);
2066 else if (strncasecmp(
2067 tline,CatString3("*",MyName,"Colorset"),Clength+9)==0)
2069 AllocColorset(colorset = atoi(&tline[Clength+9]));
2071 else if (strncasecmp(
2072 tline,CatString3("*",MyName,"IconColorset"),Clength+13)==0)
2074 AllocColorset(Iconcolorset = atoi(&tline[Clength+13]));
2076 else if (strncasecmp(
2077 tline,CatString3("*",MyName,"IconHiColorset"),Clength+15)==0)
2079 AllocColorset(IconHicolorset = atoi(&tline[Clength+15]));
2081 else if (strncasecmp(tline,CatString3("*",MyName,"Font"),Clength+5)==0)
2083 CopyStringWithQuotes(&font_string,&tline[Clength+5]);
2085 else if (strncasecmp(
2086 tline,CatString3("*",MyName,"IconFore"),Clength+9)==0)
2088 CopyString(&IconFore,&tline[Clength+9]);
2090 else if (strncasecmp(
2091 tline,CatString3("*",MyName,"IconBack"),Clength+9)==0)
2093 CopyString(&IconBack,&tline[Clength+9]);
2095 else if (strncasecmp(
2096 tline,CatString3("*",MyName,"IconHiFore"),Clength+11)==0)
2098 CopyString(&ActIconFore,&tline[Clength+11]);
2100 else if (strncasecmp(
2101 tline,CatString3("*",MyName,"IconHiBack"),Clength+11)==0)
2103 CopyString(&ActIconBack,&tline[Clength+11]);
2105 else if (strncasecmp(tline,CatString3("*",MyName,
2106 "Fore"),Clength+5)==0)
2108 CopyString(&Fore,&tline[Clength+5]);
2110 else if (strncasecmp(tline,CatString3("*",MyName,
2111 "Back"),Clength+5)==0)
2113 CopyString(&Back,&tline[Clength+5]);
2115 else if (strncasecmp(tline,CatString3("*",MyName,
2116 "Pixmap"),Clength+7)==0)
2118 CopyString(&IconwinPixmapFile,&tline[Clength+7]);
2120 else if (strncasecmp(tline,CatString3("*",MyName,
2121 "Padding"),Clength+8)==0)
2123 interval = max(0,atoi(&tline[Clength+8]));
2125 else if (strncasecmp(tline,CatString3("*",MyName,
2126 "FrameWidth"),Clength+11)==0)
2128 sscanf(&tline[Clength+11], "%d %d", &margin1, &margin2);
2129 margin1 = max(0, margin1);
2130 margin2 = max(0, margin2);
2132 else if (strncasecmp(tline,CatString3("*",MyName,
2133 "Lines"),Clength+6)==0)
2135 Lines = max(1,atoi(&tline[Clength+6]));
2137 else if (strncasecmp(tline,CatString3("*", MyName,
2138 "NoIconAction"),Clength+13) == 0)
2140 tmp = &tline[Clength+14];
2141 while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0))
2142 tmp++;
2143 if (tmp[strlen(tmp)-1] == '\n')
2144 tmp[strlen(tmp) -1] = '\0';
2145 if (AnimCommand)
2146 free(AnimCommand);
2147 AnimCommand = (char *)safemalloc((strlen(tmp) + 1) * sizeof(char));
2148 strcpy(AnimCommand, tmp);
2150 else if (strncasecmp(tline,CatString3("*",MyName,
2151 "SBWidth"),Clength+8)==0)
2153 bar_width = max(5,atoi(&tline[Clength+8]));
2155 else if (strncasecmp(tline,CatString3("*",MyName,
2156 "Placement"),Clength+10)==0)
2158 parseplacement(&tline[Clength+10]);
2160 else if (strncasecmp(tline,CatString3("*",MyName,
2161 "SetWMIconSize"),Clength+14)==0)
2163 local_flags |= SETWMICONSIZE;
2165 else if (strncasecmp(tline,CatString3("*",MyName,
2166 "HilightFocusWin"),Clength+16)==0)
2168 m_mask |= M_FOCUS_CHANGE;
2170 else if (strncasecmp(tline,CatString3("*",MyName,
2171 "UseSkipList"),Clength+10)==0)
2173 UseSkipList = True;
2175 else if (strncasecmp(tline,CatString3("*",MyName,
2176 "Resolution"),Clength+11)==0)
2178 tmp = &tline[Clength+11];
2179 while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0))
2180 tmp++;
2181 if (strncasecmp(tmp, "Desk", 4) == 0)
2183 m_mask |= M_NEW_DESK;
2184 local_flags |= CURRENT_ONLY;
2187 else if (strncasecmp(tline,CatString3("*",MyName,
2188 "Mouse"),Clength+6)==0)
2190 parsemouse(&tline[Clength + 6]);
2192 else if (strncasecmp(tline,CatString3("*",MyName,
2193 "Key"),Clength+4)==0)
2195 parsekey(&tline[Clength + 4]);
2197 else if (strncasecmp(tline,CatString3("*",MyName,
2198 "SortIcons"),Clength+10)==0)
2200 tmp = &tline[Clength+10];
2201 while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0))
2202 tmp++;
2203 if (strlen(tmp) == 0)
2205 /* the case where no argument is given */
2206 sortby = ICONNAME;
2207 return;
2209 if (strncasecmp(tmp, "WindowName", 10) == 0)
2210 sortby = WINDOWNAME;
2211 else if (strncasecmp(tmp, "IconName", 8) == 0)
2212 sortby = ICONNAME;
2213 else if (strncasecmp(tmp, "ResClass", 8) == 0)
2214 sortby = RESCLASS;
2215 else if (strncasecmp(tmp, "ResName", 7) == 0)
2216 sortby = RESNAME;
2218 else if (strncasecmp(tline,CatString3("*",MyName,
2219 "HideSC"),Clength+7)==0)
2221 tmp = &tline[Clength+7];
2222 while(((isspace((unsigned char)*tmp))&&(*tmp != '\n'))&&(*tmp != 0))
2223 tmp++;
2224 if (strncasecmp(tmp, "Horizontal", 10) == 0)
2225 local_flags |= HIDE_H;
2226 else if (strncasecmp(tmp, "Vertical", 8) == 0)
2227 local_flags |= HIDE_V;
2229 else if (strncasecmp(tline,CatString3("*",MyName,
2230 ""),Clength+1)==0)
2232 parseicon(&tline[Clength + 1]);
2234 else if (strncasecmp(tline,"ImagePath",9)==0)
2236 CopyString(&imagePath,&tline[9]);
2238 else if (strncasecmp(tline,"ClickTime",9)==0)
2240 ClickTime = atoi(&tline[9]);
2243 GetConfigLine(fd,&tline);
2246 return;
2249 void parseicon(char *tline)
2251 int len;
2252 struct iconfile *tmp;
2253 char *ptr, *start, *end;
2255 tmp = (struct iconfile *)safemalloc(sizeof(struct iconfile));
2256 memset(tmp, 0, sizeof(struct iconfile));
2258 /* windowname */
2259 tmp->name = stripcpy2(tline);
2260 if(tmp->name == NULL){
2261 free(tmp);
2262 return;
2265 /* skip windowname, based on strpcpy3 of configure.c */
2266 while((*tline != '"')&&(tline != NULL))
2267 tline++;
2268 if(*tline != 0)
2269 tline++;
2270 while((*tline != '"')&&(tline != NULL))
2271 tline++;
2272 if(*tline == 0){
2273 free(tmp);
2274 return;
2276 tline++;
2278 /* file */
2279 /* skip spaces */
2280 while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0))
2281 tline++;
2282 start = tline;
2283 end = tline;
2284 while(!isspace((unsigned char)*end)&&(*end != '\n')&&(*end != 0))
2285 end++;
2286 len = end - start;
2287 ptr = safemalloc(len+1);
2288 strncpy(ptr, start, len);
2289 ptr[len] = 0;
2290 tmp->iconfile = ptr;
2292 if (strcmp(tmp->name, "*") == 0)
2293 DefaultIcon = tmp;
2295 tmp->next = NULL;
2297 if (IconListHead == NULL)
2298 IconListHead = IconListTail = tmp;
2299 else{
2300 IconListTail->next = tmp;
2301 IconListTail = tmp;
2305 void parseplacement(char *tline)
2307 char p[240], s[240];
2309 sscanf(tline, "%s %s", p, s);
2311 if (strncasecmp(p, "Left", 4) == 0)
2312 primary = LEFT;
2313 else if (strncasecmp(p, "Right", 5) == 0)
2314 primary = RIGHT;
2315 else if (strncasecmp(p, "Top", 3) == 0)
2316 primary = TOP;
2317 else if (strncasecmp(p, "Bottom", 6) == 0)
2318 primary = BOTTOM;
2320 if (strncasecmp(s, "Left", 4) == 0)
2321 secondary = LEFT;
2322 else if (strncasecmp(s, "Right", 5) == 0)
2323 secondary = RIGHT;
2324 else if (strncasecmp(s, "Top", 3) == 0)
2325 secondary = TOP;
2326 else if (strncasecmp(s, "Bottom", 6) == 0)
2327 secondary = BOTTOM;
2330 void parsemouse(char *tline)
2332 struct mousefunc *f = NULL;
2333 int len;
2334 int n;
2335 int b;
2336 char *ptr,*start,*end,*tmp;
2338 f = (struct mousefunc *)safemalloc(sizeof(struct mousefunc));
2339 memset(f, 0, sizeof(struct mousefunc));
2341 /* skip spaces */
2342 while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0))
2343 tline++;
2344 start = tline;
2345 end = tline;
2346 while((!isspace((unsigned char)*end))&&(*end!='\n')&&(*end!=0))
2347 end++;
2348 n = sscanf(start, "%d", &b);
2349 if (n > 0 && b >= 0 && b <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)
2350 f->mouse = b;
2351 else
2352 f->mouse = -1;
2353 /* click or doubleclick */
2354 tline = end;
2355 /* skip spaces */
2356 while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0))
2357 tline++;
2358 start = tline;
2359 end = tline;
2360 while((!isspace((unsigned char)*end))&&(*end!='\n')&&(*end!=0))
2361 end++;
2362 if (strncasecmp(start, "Click", 5) == 0)
2363 f->type = CLICK;
2364 else if (strncasecmp(start, "DoubleClick", 11) == 0)
2366 f->type = DOUBLE_CLICK;
2367 have_double_click = True;
2370 /* actions */
2371 tline = end;
2372 /* skip spaces */
2373 while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0))
2374 tline++;
2375 start = tline;
2376 end = tline;
2377 tmp = tline;
2378 while((*tmp!='\n')&&(*tmp!=0)){
2379 if (!isspace((unsigned char)*tmp))
2380 end = tmp;
2381 tmp++;
2383 end++;
2384 len = end - start;
2385 ptr = safemalloc(len+1);
2386 strncpy(ptr, start, len);
2387 ptr[len] = 0;
2388 f->action = ptr;
2389 f->next = MouseActions;
2390 MouseActions = f;
2394 parsekey
2395 Based on part of AddFunckey() of configure.c in Fvwm.
2396 Copyright 1988, Evans and Sutherland Computer Corporation,
2397 Copyright 1989, Massachusetts Institute of Technology,
2398 Copyright 1993, Robert Nation.
2400 void parsekey(char *tline)
2402 struct keyfunc *k;
2403 int nlen, alen;
2404 char *nptr, *aptr, *start, *end, *tmp;
2405 int i, kmin, kmax;
2406 KeySym keysym;
2408 /* skip spaces */
2409 while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0))
2410 tline++;
2411 start = tline;
2412 end = tline;
2413 while((!isspace((unsigned char)*end))&&(*end!='\n')&&(*end!=0))
2414 end++;
2415 nlen = end - start;
2416 nptr = safemalloc(nlen+1);
2417 strncpy(nptr, start, nlen);
2418 nptr[nlen] = 0;
2420 /* actions */
2421 tline = end;
2422 /* skip spaces */
2423 while(isspace((unsigned char)*tline)&&(*tline != '\n')&&(*tline != 0))
2424 tline++;
2425 start = tline;
2426 end = tline;
2427 tmp = tline;
2428 while((*tmp!='\n')&&(*tmp!=0)){
2429 if (!isspace((unsigned char)*tmp))
2430 end = tmp;
2431 tmp++;
2433 end++;
2434 alen = end - start;
2435 aptr = safemalloc(alen+1);
2436 strncpy(aptr, start, alen);
2437 aptr[alen] = 0;
2439 if ((keysym = XStringToKeysym(nptr)) == NoSymbol ||
2440 XKeysymToKeycode(dpy, keysym) == 0){
2441 free(nptr);
2442 free(aptr);
2443 return;
2446 XDisplayKeycodes(dpy, &kmin, &kmax);
2447 for (i=kmin; i<=kmax; i++)
2448 if (XKeycodeToKeysym(dpy, i, 0) == keysym)
2450 k = (struct keyfunc *)safemalloc(sizeof(struct keyfunc));
2451 memset(k, 0, sizeof(struct keyfunc));
2452 k->name = nptr;
2453 k->keycode = i;
2454 k->action = aptr;
2455 k->next = KeyActions;
2456 KeyActions = k;
2461 * change_window_name
2462 * Original work from GoodStuff:
2463 * Copyright 1993, Robert Nation.
2465 void change_window_name(char *str)
2467 XTextProperty name;
2469 if (XStringListToTextProperty(&str,1,&name) == 0)
2471 fprintf(stderr,"%s: cannot allocate window name",MyName);
2472 return;
2474 XSetWMName(dpy,main_win,&name);
2475 XSetWMIconName(dpy,main_win,&name);
2476 XFree(name.value);
2480 * My_XNextEvent
2481 * Original work from GoodStuff:
2482 * Copyright 1993, Robert Nation.
2484 int My_XNextEvent(Display *dpy, XEvent *event)
2486 fd_set in_fdset;
2487 static int miss_counter = 0;
2489 if(FPending(dpy))
2491 FNextEvent(dpy,event);
2492 return 1;
2495 FD_ZERO(&in_fdset);
2496 FD_SET(x_fd,&in_fdset);
2497 FD_SET(fd[1],&in_fdset);
2499 if (fvwmSelect(fd_width, &in_fdset, 0, 0, NULL) > 0)
2502 if(FD_ISSET(x_fd, &in_fdset))
2504 if(FPending(dpy))
2506 FNextEvent(dpy,event);
2507 miss_counter = 0;
2508 return 1;
2510 else
2511 miss_counter++;
2512 if(miss_counter > 100)
2513 exit(0);
2516 if(FD_ISSET(fd[1], &in_fdset))
2518 FvwmPacket* packet = ReadFvwmPacket(fd[1]);
2519 if ( packet == NULL )
2520 exit(0);
2521 else
2522 process_message( packet->type, packet->body );
2525 return 0;
2529 * process_message
2530 * Based on ProcessMassage() from FvwmWinList:
2531 * Copyright 1994, Mike Finger.
2533 int diffx, diffy;
2534 void process_message(unsigned long type, unsigned long *body)
2536 struct icon_info *tmp = NULL, *old;
2537 char *str;
2538 long olddesk;
2539 struct ConfigWinPacket *cfgpacket = (void *) body;
2541 switch(type)
2543 case M_CONFIGURE_WINDOW:
2544 if (cfgpacket->w == main_win)
2546 Shaded = IS_SHADED(cfgpacket);
2548 if (SwallowerWin && cfgpacket->w == SwallowerWin)
2550 SwallowerShaded = IS_SHADED(cfgpacket);
2552 if (ready)
2554 tmp = Head;
2555 while(tmp != NULL)
2557 if (tmp->id == cfgpacket->w)
2559 int remove=0,add=0;
2561 if (IS_ICON_SUPPRESSED(cfgpacket) != IS_ICON_SUPPRESSED(tmp))
2563 if (IS_ICON_SUPPRESSED(cfgpacket))
2564 add = 1;
2565 else
2566 remove = 1;
2567 SET_ICON_SUPPRESSED(tmp,IS_ICON_SUPPRESSED(cfgpacket));
2569 if (UseSkipList &&
2570 DO_SKIP_WINDOW_LIST(cfgpacket) != DO_SKIP_WINDOW_LIST(tmp))
2572 if (!DO_SKIP_WINDOW_LIST(cfgpacket))
2573 add = 1;
2574 else
2575 remove = 1;
2576 SET_DO_SKIP_WINDOW_LIST(tmp,DO_SKIP_WINDOW_LIST(cfgpacket));
2578 if ((local_flags & CURRENT_ONLY) &&
2579 tmp->desk != cfgpacket->desk && !IS_STICKY_ACROSS_DESKS(tmp))
2581 olddesk = tmp->desk;
2582 tmp->desk = cfgpacket->desk;
2583 if (olddesk == CurrentDesk || tmp->desk == CurrentDesk)
2585 if (tmp->desk == CurrentDesk && sortby != UNSORT)
2586 SortItem(NULL);
2587 if (tmp->desk == CurrentDesk)
2588 add = 1;
2589 else
2590 remove = 1;
2592 }else if ((IS_STICKY_ACROSS_DESKS(cfgpacket)) &&
2593 !(IS_STICKY_ACROSS_DESKS(tmp))) /* stick */
2594 SET_STICKY_ACROSS_DESKS(tmp, True);
2595 else if (!(IS_STICKY_ACROSS_DESKS(cfgpacket)) &&
2596 (IS_STICKY_ACROSS_DESKS(tmp))){ /* unstick */
2597 SET_STICKY_ACROSS_DESKS(tmp, False);
2598 tmp->desk = cfgpacket->desk;
2600 if ((add && window_cond(tmp)) || remove) {
2601 num_icons = AdjustIconWindows();
2602 GetIconwinSize(&diffx, &diffy);
2603 if (diffy && (primary == BOTTOM || secondary == BOTTOM))
2604 icon_win_y += diffy;
2605 if (diffx && (primary == RIGHT || secondary == RIGHT))
2606 icon_win_x += diffx;
2607 if (icon_win_y < 0)
2608 icon_win_y = 0;
2609 if (icon_win_x < 0)
2610 icon_win_x = 0;
2611 if (icon_win_x + Width > icon_win_width)
2612 icon_win_x = icon_win_width - Width;
2613 if (icon_win_y + Height > icon_win_height)
2614 icon_win_y = icon_win_height - Height;
2615 XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y,
2616 icon_win_width, icon_win_height);
2617 if ((diffx || diffy) && (colorset >= 0))
2618 SetWindowBackground(dpy, icon_win, icon_win_width,
2619 icon_win_height, &Colorset[(colorset)],
2620 Pdepth, NormalGC, True);
2621 if (remove){
2622 XUnmapWindow(dpy, tmp->IconWin);
2623 if (max_icon_height != 0)
2624 XUnmapWindow(dpy, tmp->icon_pixmap_w);
2625 }else{
2626 XMapWindow(dpy, tmp->IconWin);
2627 if (max_icon_height != 0)
2628 XMapWindow(dpy, tmp->icon_pixmap_w);
2630 if (!(local_flags & HIDE_H) && diffx)
2631 RedrawHScrollbar();
2632 if (!(local_flags & HIDE_V) && diffy)
2633 RedrawVScrollbar();
2635 return;
2637 tmp = tmp->next;
2638 } /* while */
2639 break;
2641 case M_ADD_WINDOW:
2642 if (AddItem(cfgpacket) == True && ready){
2643 GetIconwinSize(&diffx, &diffy);
2644 if (diffy && (primary == BOTTOM || secondary == BOTTOM))
2645 icon_win_y += diffy;
2646 if (diffx && (primary == RIGHT || secondary == RIGHT))
2647 icon_win_x += diffx;
2648 XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y,
2649 icon_win_width, icon_win_height);
2650 if ((diffx || diffy) && (colorset >= 0))
2651 SetWindowBackground(dpy, icon_win, icon_win_width,
2652 icon_win_height, &Colorset[(colorset)],
2653 Pdepth, NormalGC, True);
2655 break;
2656 case M_DESTROY_WINDOW:
2657 if (DeleteItem(body[0]) && ready){
2658 GetIconwinSize(&diffx, &diffy);
2659 if (diffy && (primary == BOTTOM || secondary == BOTTOM))
2660 icon_win_y += diffy;
2661 if (diffx && (primary == RIGHT || secondary == RIGHT))
2662 icon_win_x += diffx;
2663 if (icon_win_y < 0)
2664 icon_win_y = 0;
2665 if (icon_win_x < 0)
2666 icon_win_x = 0;
2667 if (icon_win_x + Width > icon_win_width)
2668 icon_win_x = icon_win_width - Width;
2669 if (icon_win_y + Height > icon_win_height)
2670 icon_win_y = icon_win_height - Height;
2671 XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y,
2672 icon_win_width, icon_win_height);
2673 if ((diffx || diffy) && (colorset >= 0))
2674 SetWindowBackground(dpy, icon_win, icon_win_width,
2675 icon_win_height, &Colorset[(colorset)],
2676 Pdepth, NormalGC, True);
2677 AdjustIconWindows();
2678 if (!(local_flags & HIDE_H) && diffx)
2679 RedrawHScrollbar();
2680 if (!(local_flags & HIDE_V) && diffy)
2681 RedrawVScrollbar();
2683 break;
2684 case M_ICON_FILE:
2685 case M_RES_CLASS:
2686 UpdateItem(type, body[0], (char *)&body[3]);
2687 break;
2688 case M_VISIBLE_NAME:
2689 tmp = UpdateItem(type, body[0], (char *)&body[3]);
2690 if (!ready || tmp == NULL)
2691 break;
2692 if (sortby == WINDOWNAME && tmp->IconWin != None
2693 && window_cond(tmp) && SortItem(tmp) == True)
2694 AdjustIconWindows();
2695 break;
2696 case M_RES_NAME:
2697 if ((tmp = UpdateItem(type, body[0], (char *)&body[3])) == NULL)
2698 break;
2699 if (LookInList(tmp) && ready){
2700 if (sortby != UNSORT)
2701 SortItem(tmp);
2702 CreateIconWindow(tmp);
2703 AdjustIconWindows();
2704 if (window_cond(tmp)){
2705 if (max_icon_height != 0)
2706 XMapWindow(dpy, tmp->icon_pixmap_w);
2707 XMapWindow(dpy, tmp->IconWin);
2708 if (!(local_flags & HIDE_H))
2709 RedrawHScrollbar();
2710 if (!(local_flags & HIDE_V))
2711 RedrawVScrollbar();
2714 break;
2715 case MX_VISIBLE_ICON_NAME:
2716 tmp = UpdateItem(type, body[0], (char *)&body[3]);
2717 if (!ready || tmp == NULL)
2718 break;
2719 if (sortby != UNSORT && tmp->IconWin != None
2720 && window_cond(tmp) && SortItem(tmp) == True)
2721 AdjustIconWindows();
2722 if (tmp->IconWin != None && window_cond(tmp))
2723 RedrawIcon(tmp, 2, NULL);
2724 break;
2725 case M_DEFAULTICON:
2726 str = (char *)safemalloc(strlen((char *)&body[3])+1);
2727 strcpy(str, (char *)&body[3]);
2728 if (FvwmDefaultIcon)
2729 free(FvwmDefaultIcon);
2730 FvwmDefaultIcon = str;
2731 break;
2732 case M_ICONIFY:
2733 case M_DEICONIFY:
2734 if (ready && (tmp = SetFlag(body[0], type)) != NULL)
2735 RedrawIcon(tmp, 2, NULL);
2736 if (tmp && window_cond(tmp)) animate(tmp,body);
2737 SendUnlockNotification(fd);
2738 break;
2739 case M_FOCUS_CHANGE:
2740 if (!ready)
2741 break;
2742 tmp = Head;
2743 while(tmp != NULL){
2744 if (tmp->id == body[0]) break;
2745 tmp = tmp->next;
2747 old = Hilite;
2748 Hilite = tmp;
2749 if (old != NULL)
2750 RedrawIcon(old, redraw_flag, NULL);
2751 if (tmp != NULL)
2752 RedrawIcon(tmp, redraw_flag, NULL);
2753 break;
2754 case M_NEW_DESK:
2755 if (CurrentDesk != body[0])
2757 CurrentDesk = body[0];
2758 if (body[0] != 10000 && ready)
2760 /* 10000 is a "magic" number used in FvwmPager */
2761 if (sortby != UNSORT)
2762 SortItem(NULL);
2763 num_icons = AdjustIconWindows();
2764 GetIconwinSize(&diffx, &diffy);
2765 icon_win_x = icon_win_y = 0;
2766 if (primary == BOTTOM || secondary == BOTTOM)
2767 icon_win_y = icon_win_height - Height;
2768 if (primary == RIGHT || secondary == RIGHT)
2769 icon_win_x = icon_win_width - Width;
2770 XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y,
2771 icon_win_width, icon_win_height);
2772 XUnmapSubwindows(dpy, icon_win);
2773 if ((diffx || diffy) && (colorset >= 0))
2774 SetWindowBackground(dpy, icon_win, icon_win_width,
2775 icon_win_height, &Colorset[(colorset)],
2776 Pdepth, NormalGC, True);
2777 mapicons();
2778 if (!(local_flags & HIDE_H))
2779 RedrawHScrollbar();
2780 if (!(local_flags & HIDE_V))
2781 RedrawVScrollbar();
2784 break;
2785 case M_END_WINDOWLIST:
2786 GetIconwinSize(&diffx, &diffy);
2787 tmp = Head;
2788 while(tmp != NULL){
2789 CreateIconWindow(tmp);
2790 tmp = tmp->next;
2792 if (sortby != UNSORT)
2793 SortItem(NULL);
2794 if (primary == BOTTOM || secondary == BOTTOM)
2795 icon_win_y = icon_win_height - Height;
2796 if (primary == RIGHT || secondary == RIGHT)
2797 icon_win_x = icon_win_width - Width;
2798 XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y,
2799 icon_win_width, icon_win_height);
2800 if ((diffx || diffy) && (colorset >= 0))
2801 SetWindowBackground(dpy, icon_win, icon_win_width,
2802 icon_win_height, &Colorset[(colorset)],
2803 Pdepth, NormalGC, True);
2804 AdjustIconWindows();
2805 XMapWindow(dpy,main_win);
2806 XMapSubwindows(dpy, main_win);
2807 XMapWindow(dpy, icon_win);
2808 mapicons();
2809 ready = 1;
2810 break;
2811 case M_CONFIG_INFO:
2813 char *tline, *token;
2814 int color;
2815 tline = (char*)&(body[3]);
2816 token = PeekToken(tline, &tline);
2817 if (StrEquals(token, "Colorset")) {
2818 color = LoadColorset(tline);
2819 change_colorset(color);
2821 else if (StrEquals(token, XINERAMA_CONFIG_STRING))
2823 FScreenConfigureModule(tline);
2826 break;
2827 case MX_PROPERTY_CHANGE:
2828 if (body[0] == MX_PROPERTY_CHANGE_BACKGROUND &&
2829 (CSET_IS_TRANSPARENT_PR(colorset)) &&
2830 ((!Swallowed && body[2] == 0) || (Swallowed && body[2] == icon_win)))
2832 XClearArea(dpy, icon_win, 0,0,0,0, False);
2834 else if (body[0] == MX_PROPERTY_CHANGE_SWALLOW && body[2] == icon_win)
2836 char *str;
2838 Swallowed = body[1];
2839 str = (char *)&body[3];
2841 if (Swallowed && str)
2843 unsigned long u;
2844 if (sscanf(str,"%lu",&u) == 1)
2846 SwallowerWin = (Window)u;
2848 else
2850 SwallowerWin = 0;
2854 break;
2855 default:
2856 break;
2860 struct icon_info *SetFlag(unsigned long id, int t)
2862 struct icon_info *tmp;
2863 tmp = Head;
2865 while(tmp != NULL){
2866 if (tmp->id == id){
2867 if (t == M_ICONIFY)
2868 SET_ICONIFIED(tmp, True);
2869 else
2870 SET_ICONIFIED(tmp, False);
2871 return tmp;
2873 tmp = tmp->next;
2875 return NULL;
2878 void mapicons(void)
2880 struct icon_info *tmp;
2881 tmp = Head;
2883 while(tmp != NULL){
2884 if (window_cond(tmp)){
2885 XMapWindow(dpy, tmp->IconWin);
2886 if (max_icon_height != 0)
2887 XMapWindow(dpy, tmp->icon_pixmap_w);
2889 tmp = tmp->next;
2893 int AdjustIconWindows(void)
2895 struct icon_info *tmp;
2896 int i = 0;
2897 tmp = Head;
2899 while(tmp != NULL){
2900 if (window_cond(tmp) && tmp->IconWin != None)
2901 AdjustIconWindow(tmp, i++);
2902 tmp = tmp->next;
2904 return i;
2907 int window_cond(struct icon_info *item)
2909 if ((!(local_flags & CURRENT_ONLY) ||
2910 (IS_STICKY_ACROSS_DESKS(item)) || (item->desk == CurrentDesk)) &&
2911 IS_ICON_SUPPRESSED(item) &&
2912 (!DO_SKIP_WINDOW_LIST(item) || !UseSkipList))
2913 return 1;
2915 return 0;
2919 * AddItem
2920 * Skeleton based on AddItem() from FvwmWinList:
2921 * Copyright 1994, Mike Finger.
2923 /*Bool AddItem(unsigned long id, long desk, unsigned long flags) */
2924 Bool AddItem(ConfigWinPacket *cfgpacket)
2926 struct icon_info *new, *tmp;
2927 tmp = Head;
2929 if (cfgpacket->w == main_win || IS_TRANSIENT(cfgpacket))
2930 return False;
2932 while (tmp != NULL){
2933 if (tmp->id == cfgpacket->w ||
2934 (tmp->wmhints && (tmp->wmhints->flags & IconWindowHint) &&
2935 tmp->wmhints->icon_window == cfgpacket->w))
2936 return False;
2937 tmp = tmp->next;
2940 new = (struct icon_info *)safemalloc(sizeof(struct icon_info));
2941 memset(new, 0, sizeof(struct icon_info));
2942 new->desk = cfgpacket->desk;
2943 new->id = cfgpacket->w;
2944 new->extra_flags = DEFAULTICON;
2945 memcpy(&(new->flags), &(cfgpacket->flags), sizeof(new->flags));
2946 SET_ICON_OURS(new, True);
2947 SET_PIXMAP_OURS(new, True);
2949 /* add new item to the head of the list
2951 new->prev = NULL;
2952 new->next = Head;
2953 if (Head != NULL)
2954 Head->prev = new;
2955 else
2956 Tail = new;
2957 Head = new; */
2959 /* add new item to the tail of the list */
2960 new->prev = Tail;
2961 if (Tail != NULL)
2962 Tail->next = new;
2963 else
2964 Head = new;
2965 Tail = new;
2967 if (window_cond(new)) {
2968 num_icons++;
2969 return True;
2972 return False;
2976 * Deletetem
2977 * Skeleton based on DeleteItem() from FvwmWinList:
2978 * Copyright 1994, Mike Finger.
2980 Bool DeleteItem(unsigned long id)
2982 struct icon_info *tmp = Head;
2984 while(tmp != NULL){
2985 if (tmp->id == id){
2986 if (window_cond(tmp))
2987 num_icons--;
2988 if (Hilite == tmp)
2989 Hilite = NULL;
2990 if ((tmp->icon_pixmap_w != None) && (IS_ICON_OURS(tmp)))
2991 XDestroyWindow(dpy, tmp->icon_pixmap_w);
2992 if (tmp->IconWin != None)
2993 XDestroyWindow(dpy, tmp->IconWin);
2994 if (tmp == Head){
2995 Head = tmp->next;
2996 if (Head != NULL)
2997 Head->prev = NULL;
2998 else
2999 Tail = NULL;
3000 }else {
3001 if (Tail == tmp)
3002 Tail = tmp->prev;
3003 tmp->prev->next = tmp->next;
3004 if (tmp->next != NULL)
3005 tmp->next->prev = tmp->prev;
3007 freeitem(tmp, 1);
3008 return True;
3010 tmp = tmp->next;
3012 return False;
3016 * UpdateItem
3017 * Skeleton based on UpdateItem() from FvwmWinList:
3018 * Copyright 1994, Mike Finger.
3020 struct icon_info *UpdateItem(unsigned long type, unsigned long id, char *item)
3022 struct icon_info *tmp;
3023 char *str;
3024 XClassHint classhint;
3025 int ret;
3027 tmp = Head;
3028 while (tmp != NULL){
3029 if (tmp->id == id){
3030 str = (char *)safemalloc(strlen(item)+1);
3031 strcpy(str, item);
3033 switch (type){
3034 case MX_VISIBLE_ICON_NAME:
3035 if (tmp->name)
3036 free(tmp->name);
3037 tmp->name = str;
3038 return tmp;
3039 case M_ICON_FILE:
3040 if (tmp->icon_file)
3041 free(tmp->icon_file);
3042 tmp->icon_file = str;
3043 tmp->extra_flags &= ~DEFAULTICON;
3044 return tmp;
3045 case M_VISIBLE_NAME:
3046 if (tmp->window_name)
3047 free(tmp->window_name);
3048 tmp->window_name = str;
3049 return tmp;
3050 case M_RES_CLASS:
3051 if (tmp->res_class)
3052 free(tmp->res_class);
3053 tmp->res_class = str;
3054 ret = 0;
3055 if (sortby == RESCLASS && strcmp(NoClass, str) == 0
3056 && !(ret = XGetClassHint(dpy, tmp->id, &classhint))){
3057 tmp->extra_flags |= NOCLASS;
3059 if (ret){
3060 if (classhint.res_class != NULL)
3061 XFree(classhint.res_class);
3062 if (classhint.res_name != NULL)
3063 XFree(classhint.res_name);
3065 return tmp;
3066 case M_RES_NAME:
3067 if (tmp->res_name)
3068 free(tmp->res_name);
3069 tmp->res_name = str;
3070 ret = 0;
3071 if (sortby == RESNAME && strcmp(NoResource, str) == 0
3072 && !(ret = XGetClassHint(dpy, tmp->id, &classhint)))
3073 tmp->extra_flags |= NONAME;
3074 if (ret){
3075 if (classhint.res_class != NULL)
3076 XFree(classhint.res_class);
3077 if (classhint.res_name != NULL)
3078 XFree(classhint.res_name);
3080 return tmp;
3083 tmp = tmp->next;
3085 return NULL;
3088 Bool SortItem(struct icon_info *item)
3090 struct icon_info *tmp1=Head, *a, *b, *tmp2;
3092 if (tmp1 == NULL)
3093 return False;
3095 if (item != NULL &&
3096 ((itemcmp(item->prev, item) <= 0) &&
3097 (itemcmp(item->next, item) >= 0)))
3098 return False;
3100 while (tmp1->next != NULL){
3101 tmp2 = MinItem(tmp1);
3102 if (tmp1 == tmp2){
3103 tmp1 = tmp1->next;
3104 continue;
3106 if (tmp1 == Head)
3107 Head = tmp2;
3108 a = tmp1->prev;
3109 b = tmp1->next;
3110 if (tmp1->prev != NULL)
3111 tmp1->prev->next = tmp2;
3112 if (b != tmp2)
3113 tmp1->next->prev = tmp2;
3114 if (b != tmp2)
3115 tmp2->prev->next = tmp1;
3116 if (tmp2->next != NULL)
3117 tmp2->next->prev = tmp1;
3118 if (b == tmp2){
3119 tmp1->prev = tmp2;
3120 tmp1->next = tmp2->next;
3121 tmp2->prev = a;
3122 tmp2->next = tmp1;
3123 }else{
3124 tmp1->prev = tmp2->prev;
3125 tmp1->next = tmp2->next;
3126 tmp2->prev = a;
3127 tmp2->next = b;
3129 tmp1 = b;
3131 Tail = tmp1;
3133 return True;
3136 struct icon_info *MinItem(struct icon_info *head)
3138 struct icon_info *tmp, *i_min;
3140 if (head == NULL)
3141 return NULL;
3143 i_min = head;
3144 tmp = head->next;
3145 while (tmp != NULL){
3146 if (itemcmp(i_min, tmp) > 0)
3147 i_min = tmp;
3148 tmp = tmp->next;
3150 return i_min;
3153 int itemcmp(struct icon_info *item1, struct icon_info *item2)
3155 int ret1, ret2;
3157 if (item1 == NULL){
3158 if (item2 == NULL)
3159 return 0;
3160 else
3161 return -1;
3162 } else if (item2 == NULL)
3163 return 1;
3165 /* skip items not on the current desk */
3166 ret1 = window_cond(item1);
3167 ret2 = window_cond(item2);
3168 if (!ret1 || !ret2)
3169 return (ret1 - ret2);
3171 ret1 = 0;
3172 ret2 = strcmp(item1->name, item2->name);
3174 switch(sortby){
3175 case WINDOWNAME:
3176 ret1 = strcmp(item1->window_name, item2->window_name);
3177 break;
3178 case RESCLASS:
3179 if ((item1->extra_flags & NOCLASS)){
3180 if ((item2->extra_flags & NOCLASS))
3181 ret1 = 0;
3182 else if (!(item2->extra_flags & NOCLASS))
3183 ret1 = -1;
3184 }else if ((item2->extra_flags & NOCLASS))
3185 ret1 = 1;
3186 else
3187 ret1 = strcmp(item1->res_class, item2->res_class);
3188 break;
3189 case RESNAME:
3190 if ((item1->extra_flags & NOCLASS)){
3191 if ((item2->extra_flags & NOCLASS))
3192 ret1 = 0;
3193 else if (!(item2->extra_flags & NOCLASS))
3194 ret1 = -1;
3195 }else if ((item2->extra_flags & NOCLASS))
3196 ret1 = 1;
3197 else
3198 ret1 = strcmp(item1->res_name, item2->res_name);
3199 break;
3200 default:
3201 break;
3203 return (ret1 != 0 ? ret1 : ret2);
3207 void ShowItem(struct icon_info *head)
3209 struct icon_info *tmp;
3211 fprintf(stderr, "The contents of item are as follows:\n");
3212 tmp = head;
3213 while (tmp != NULL){
3214 fprintf(stderr, "id:%x name:%s resname:%s class%s iconfile:%s\n",
3215 tmp->id,
3216 tmp->name == NULL ? "NULL" : tmp->name, tmp->res_name,
3217 tmp->res_class, tmp->icon_file);
3218 tmp = tmp->next;
3222 void ShowAction(void)
3224 struct mousefunc *tmp;
3226 tmp = MouseActions;
3227 while (tmp != NULL){
3228 fprintf(stderr, "mouse:%d type %d action:%s\n", tmp->mouse,
3229 tmp->type, tmp->action);
3230 tmp = tmp->next;
3234 void ShowKAction(void)
3236 struct keyfunc *tmp;
3238 tmp = KeyActions;
3239 while (tmp != NULL){
3240 fprintf(stderr, "key:%s keycode:%d action:%s\n", tmp->name,
3241 tmp->keycode, tmp->action);
3242 tmp = tmp->next;
3247 void freeitem(struct icon_info *item, int d)
3249 if (item == NULL)
3250 return;
3252 if (!(IS_ICON_OURS(item))){
3253 if (max_icon_height != 0)
3254 XUnmapWindow(dpy, item->icon_pixmap_w);
3255 if (d == 0)
3256 XReparentWindow(dpy, item->icon_pixmap_w, Root, 0, 0);
3259 if (item->name != NULL)
3260 free(item->name);
3261 if (item->window_name != NULL)
3262 free(item->window_name);
3263 if (item->res_name != NULL)
3264 free(item->res_name);
3265 if (item->res_class != NULL)
3266 free(item->res_class);
3267 if (item->icon_file != NULL)
3268 free(item->icon_file);
3269 if (item->iconPixmap != None)
3270 XFreePixmap(dpy, item->iconPixmap);
3271 if (item->icon_maskPixmap != None &&
3272 (item->wmhints == NULL ||
3273 !(item->wmhints->flags & (IconPixmapHint|IconWindowHint))))
3275 XFreePixmap(dpy, item->icon_maskPixmap);
3277 if (item->iconPixmap != None)
3278 XFreePixmap(dpy, item->icon_alphaPixmap);
3279 if (item->icon_alloc_pixels != NULL)
3281 if (item->icon_nalloc_pixels != 0)
3283 PictureFreeColors(
3284 dpy, Pcmap, item->icon_alloc_pixels,
3285 item->icon_nalloc_pixels, 0,
3286 item->icon_no_limit);
3288 free(item->icon_alloc_pixels);
3290 if (item->wmhints != NULL)
3291 XFree(item->wmhints);
3292 free(item);
3297 * CheckActionType
3298 * Based on functions.c from Fvwm:
3300 static int CheckActionType(
3301 int x, int y, XEvent *d, Bool may_time_out, Bool is_button_pressed)
3303 int xcurrent,ycurrent,total = 0;
3304 int dist;
3305 Bool do_sleep = False;
3307 xcurrent = x;
3308 ycurrent = y;
3309 dist = DEFAULT_MOVE_THRESHOLD;
3311 while (total < ClickTime || !may_time_out)
3313 if (!(x - xcurrent <= dist && xcurrent - x <= dist &&
3314 y - ycurrent <= dist && ycurrent - y <= dist))
3316 return TIMEOUT;
3319 if (do_sleep)
3321 usleep(20000);
3323 else
3325 usleep(1);
3326 do_sleep = 1;
3328 total += 20;
3329 if (FCheckMaskEvent(dpy, ButtonReleaseMask|ButtonMotionMask|
3330 PointerMotionMask|ButtonPressMask|ExposureMask, d))
3332 do_sleep = 0;
3333 switch (d->xany.type)
3335 case ButtonRelease:
3336 return CLICK;
3337 case MotionNotify:
3338 if ((d->xmotion.state & DEFAULT_ALL_BUTTONS_MASK) ||
3339 !is_button_pressed)
3341 xcurrent = d->xmotion.x_root;
3342 ycurrent = d->xmotion.y_root;
3344 else
3346 return CLICK;
3348 break;
3349 case ButtonPress:
3350 if (may_time_out)
3351 is_button_pressed = True;
3352 break;
3353 default:
3354 /* can't happen */
3355 break;
3360 return TIMEOUT;
3365 * ExecuteAction
3366 * Based on part of ComplexFunction() of functions.c from fvwm:
3367 Copyright 1988, Evans and Sutherland Computer Corporation,
3368 Copyright 1989, Massachusetts Institute of Technology,
3369 Copyright 1993, Robert Nation.
3371 void ExecuteAction(int x, int y, struct icon_info *item)
3373 int type = NO_CLICK;
3374 XEvent *ev;
3375 XEvent d;
3376 struct mousefunc *tmp;
3378 /* Wait and see if we have a click, or a move */
3379 /* wait forever, see if the user releases the button */
3380 type = CheckActionType(x, y, &d, False, True);
3381 if (type == CLICK)
3383 ev = &d;
3384 /* If it was a click, wait to see if its a double click */
3385 if (have_double_click)
3387 type = CheckActionType(x, y, &d, True, False);
3388 switch (type)
3390 case CLICK:
3391 type = DOUBLE_CLICK;
3392 ev = &d;
3393 break;
3394 case TIMEOUT:
3395 type = CLICK;
3396 break;
3397 default:
3398 /* can't happen */
3399 break;
3403 tmp = MouseActions;
3405 while (tmp != NULL){
3406 if ((tmp->mouse == d.xbutton.button || tmp->mouse == 0) &&
3407 tmp->type == type)
3409 MySendFvwmPipe(fd, tmp->action, item->id);
3410 return;
3412 tmp = tmp->next;
3416 void ExecuteKey(XEvent event)
3418 struct icon_info *item;
3419 struct keyfunc *tmp;
3421 if ((item = Hilite) == NULL)
3422 if ((item = Head) == NULL)
3423 return;
3425 tmp = KeyActions;
3426 event.xkey.keycode =
3427 XKeysymToKeycode(dpy,XKeycodeToKeysym(dpy,event.xkey.keycode,0));
3428 while (tmp != NULL){
3429 if (tmp->keycode == event.xkey.keycode){
3430 MySendFvwmPipe(fd, tmp->action, item->id);
3431 return;
3433 tmp = tmp->next;
3438 LookInList
3439 Based on part of LookInList() of add_window.c from fvwm:
3440 Copyright 1988, Evans and Sutherland Computer Corporation,
3441 Copyright 1989, Massachusetts Institute of Technology,
3442 Copyright 1993, Robert Nation.
3444 int LookInList(struct icon_info *item)
3446 int isdefault=1;
3447 char *value=NULL;
3448 struct iconfile *nptr;
3450 if (IconListHead == NULL) {
3451 if ((item->extra_flags & DEFAULTICON) && (FvwmDefaultIcon != NULL))
3453 if (item->icon_file)
3454 free(item->icon_file);
3455 item->icon_file = safestrdup(FvwmDefaultIcon);
3457 return 1;
3461 for (nptr = IconListHead; nptr != NULL; nptr = nptr->next){
3462 if (nptr == DefaultIcon)
3463 isdefault = 1;
3465 if (matchWildcards(nptr->name, item->res_class) == True){
3466 value = nptr->iconfile;
3467 if (nptr != DefaultIcon)
3468 isdefault = 0;
3471 if (matchWildcards(nptr->name, item->res_name) == True){
3472 value = nptr->iconfile;
3473 if (nptr != DefaultIcon)
3474 isdefault = 0;
3477 if (matchWildcards(nptr->name, item->window_name) == True){
3478 value = nptr->iconfile;
3479 if (nptr != DefaultIcon)
3480 isdefault = 0;
3484 if (!isdefault)
3486 if (item->icon_file)
3487 free(item->icon_file);
3488 if (value)
3489 item->icon_file = safestrdup(value);
3490 else
3491 item->icon_file = NULL;
3492 item->extra_flags &= ~DEFAULTICON;
3494 else if ((item->extra_flags & DEFAULTICON))
3496 if (DefaultIcon != NULL)
3498 if (item->icon_file)
3499 free(item->icon_file);
3500 item->icon_file = safestrdup(DefaultIcon->iconfile);
3502 else if (FvwmDefaultIcon != NULL)
3504 if (item->icon_file)
3505 free(item->icon_file);
3506 item->icon_file = safestrdup(FvwmDefaultIcon);
3510 /* Icon is not shown if "-" is specified */
3511 if (item->icon_file != NULL && (strcmp(item->icon_file, "-") == 0)){
3512 DeleteItem(item->id);
3513 return 0;
3515 return 1;
3519 strcpy
3520 Based on stripcpy2() of configure.c from Fvwm:
3521 Copyright 1988, Evans and Sutherland Computer Corporation,
3522 Copyright 1989, Massachusetts Institute of Technology,
3523 Copyright 1993, Robert Nation.
3525 char *stripcpy2(char *source)
3527 char *ptr;
3528 int count = 0;
3529 while((*source != '"')&&(*source != 0))
3530 source++;
3531 if(*source == 0)
3532 return 0;
3534 source++;
3535 ptr = source;
3536 while((*ptr!='"')&&(*ptr != 0)){
3537 ptr++;
3538 count++;
3540 ptr = safemalloc(count+1);
3541 strncpy(ptr,source,count);
3542 ptr[count]=0;
3543 return ptr;
3547 Error handler
3549 static int
3550 myErrorHandler(Display *dpy, XErrorEvent *event)
3552 if((event->error_code == BadAccess) && do_allow_bad_access)
3554 /* may happen when reparenting a icon window */
3555 was_bad_access = 1;
3556 return 0;
3558 /* some errors are ignored, mostly due to colorsets changing too fast */
3559 if (event->error_code == BadWindow)
3560 return 0;
3561 if (event->error_code == BadDrawable)
3562 return 0;
3563 if (event->error_code == BadPixmap)
3564 return 0;
3565 if (event->error_code == FRenderGetErrorCodeBase() + FRenderBadPicture)
3566 return 0;
3568 PrintXErrorAndCoredump(dpy, event, MyName);
3569 return 0;