2 /* FvwmWinList Module for Fvwm.
4 * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or
7 * The functions in this source file that are the original work of Mike Finger.
9 * No guarantees or warantees or anything are provided or implied in any way
10 * whatsoever. Use this program at your own risk. Permission to use this
11 * program for any purpose is given, as long as the copyright is kept intact.
13 * Things to do: Convert to C++ (In Progress)
16 /* This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include "libs/fvwmlib.h"
37 #include "libs/Colorset.h"
38 #include "libs/Flocale.h"
40 #include "FvwmWinList.h"
41 #include "ButtonArray.h"
43 #include "libs/PictureGraphics.h"
44 #include "libs/Rectangles.h"
45 #include "libs/Graphics.h"
47 extern FlocaleFont
*FButtonFont
;
48 extern FlocaleWinString
*FwinString
;
51 extern GC shadow
[MAX_COLOUR_SETS
],hilite
[MAX_COLOUR_SETS
];
52 extern GC graph
[MAX_COLOUR_SETS
],background
[MAX_COLOUR_SETS
];
53 extern int colorset
[MAX_COLOUR_SETS
];
54 extern Pixmap pixmap
[MAX_COLOUR_SETS
];
55 extern int LeftJustify
, TruncateLeft
, ShowFocus
;
57 extern int win_height
;
59 extern long CurrentDesk
;
60 extern int ShowCurrentDesk
;
61 extern int UseSkipList
;
64 * Button handling functions and procedures
68 ButtonNew - Allocates and fills a new button structure
70 Button
*ButtonNew(char *title
, FvwmPicture
*p
, int up
)
74 new = (Button
*)safemalloc(sizeof(Button
));
75 memset(new, 0, sizeof(Button
));
78 new->title
= safemalloc(strlen(title
)+1);
79 strcpy(new->title
, title
);
83 new->p
.picture
= p
->picture
;
84 new->p
.mask
= p
->mask
;
85 new->p
.alpha
= p
->alpha
;
86 new->p
.width
= p
->width
;
87 new->p
.height
= p
->height
;
88 new->p
.depth
= p
->depth
;
90 new->p
.picture
= None
;
102 InitArray - Initialize the arrary of buttons
104 void InitArray(ButtonArray
*array
,int x
,int y
,int w
,int h
,int rw
)
107 array
->head
=array
->tail
=NULL
;
116 UpdateArray - Update the array width
118 void UpdateArray(ButtonArray
*array
, int w
)
122 if (w
>= 0 && array
->w
!= w
)
125 for(temp
= array
->head
; temp
!= NULL
; temp
= temp
->next
)
126 temp
->needsupdate
= 1;
131 Reorder buttons in window list order (see List.c:ReorderList()
133 void ReorderButtons(ButtonArray
*array
, int ButNum
, int FlipFocus
)
135 Button
*temp
= array
->head
, *prev
= NULL
;
138 if (!ButNum
) return; /* this is a NOP if ButNum == 0 */
139 /* find the item, marking everything from the top as needing update */
140 while (temp
&& i
!= ButNum
) {
142 temp
->needsupdate
= True
;
147 if (!temp
) return; /* we fell off the list */
149 /* prev is guaranteed to be !NULL */
151 /* take care of the tail of the list */
152 if (array
->tail
== temp
) array
->tail
= prev
;
154 prev
->next
= temp
->next
;
156 temp
->next
= array
->head
;
160 array
->tail
->next
= array
->head
;
161 /* rotate around by changing the list pointers */
164 /* unclose the end */
168 /* Focus requires the entire array to be redrawn */
170 for (temp
= array
->head
; temp
; temp
= temp
->next
)
171 temp
->needsupdate
= True
;
175 AddButton - Allocate space for and add the button to the bottom
177 int AddButton(ButtonArray
*array
, char *title
, FvwmPicture
*p
, int up
)
181 new = ButtonNew(title
, p
, up
);
182 if (array
->head
== NULL
)
184 array
->head
= array
->tail
= new;
188 array
->tail
->next
= new;
193 /* in Taskbar this replaces below ArrangeButtonArray (array);*/
196 new->tw
=FlocaleTextWidth(FButtonFont
,title
,strlen(title
));
198 new->truncatewidth
=0;
202 new->reliefwidth
=array
->rw
;
204 return (array
->count
-1);
208 UpdateButton - Change the name/state of a button
210 int UpdateButton(ButtonArray
*array
, int butnum
, char *title
, int up
)
214 temp
=find_n(array
,butnum
);
219 temp
->title
=(char *)saferealloc(temp
->title
,strlen(title
)+1);
220 strcpy(temp
->title
,title
);
221 temp
->tw
=FlocaleTextWidth(FButtonFont
,title
,strlen(title
));
222 temp
->truncatewidth
= 0;
233 /* -------------------------------------------------------------------------
234 UpdateButtonPicture - Change the picture of a button
235 ------------------------------------------------------------------------- */
236 int UpdateButtonPicture(ButtonArray
*array
, int butnum
, FvwmPicture
*p
)
239 temp
=find_n(array
,butnum
);
240 if (temp
== NULL
) return -1;
241 if (temp
->p
.picture
!= p
->picture
|| temp
->p
.mask
!= p
->mask
)
243 temp
->p
.picture
= p
->picture
;
244 temp
->p
.mask
= p
->mask
;
245 temp
->p
.alpha
= p
->alpha
;
246 temp
->p
.width
= p
->width
;
247 temp
->p
.height
= p
->height
;
248 temp
->p
.depth
= p
->depth
;
249 temp
->needsupdate
= 1;
254 void UpdateButtonIconified(ButtonArray
*array
, int butnum
, int iconified
)
258 temp
=find_n(array
,butnum
);
261 temp
->is_iconified
= !!iconified
;
268 UpdateButtonSet - Change colour set of a button between odd and even
270 int UpdateButtonSet(ButtonArray
*array
, int butnum
, int set
)
274 btn
=find_n(array
, butnum
);
277 if ((btn
->set
& 1) != set
)
279 btn
->set
= (btn
->set
& 2) | set
;
280 btn
->needsupdate
= 1;
287 UpdateButtonDeskFlags - Change desk and flags of a button
289 int UpdateButtonDeskFlags(ButtonArray
*array
, int butnum
, long desk
,
290 int is_sticky
, int skip
)
294 btn
= find_n(array
, butnum
);
298 btn
->is_sticky
= is_sticky
;
306 RemoveButton - Delete a button from the list
308 void RemoveButton(ButtonArray
*array
, int butnum
)
310 Button
*temp
, *to_die
;
313 to_die
= array
->head
;
316 temp
= find_n(array
, butnum
-1);
317 if (temp
== NULL
) return;
320 if ( !to_die
) return;
322 if (array
->tail
== to_die
)
325 array
->head
= to_die
->next
;
327 temp
->next
= to_die
->next
;
331 if (temp
&& temp
!= array
->head
)
333 for (; temp
!=NULL
; temp
=temp
->next
)
334 temp
->needsupdate
= 1;
338 find_n - Find the nth button in the list (Use internally)
340 Button
*find_n(ButtonArray
*array
, int n
)
346 for(i
=0;i
<n
&& temp
!=NULL
;i
++,temp
=temp
->next
);
351 FreeButton - Free space allocated to a button
353 void FreeButton(Button
*ptr
)
356 if (ptr
->title
!=NULL
) free(ptr
->title
);
362 FreeAllButtons - Free the whole array of buttons
364 void FreeAllButtons(ButtonArray
*array
)
367 for(temp
=array
->head
;temp
!=NULL
;)
376 DoButton - Draw the specified button. (Used internally)
379 Button
*button
, int x
, int y
, int w
, int h
, Bool clear_bg
, XEvent
*evp
)
381 int up
,Fontheight
,newx
,set
,len
;
388 FvwmRenderAttributes fra
;
389 XRectangle rect
,inter
;
392 /* The margin we want between the relief/text/pixmaps */
393 #define INNER_MARGIN 2
398 if (!frect_get_intersection(
400 evp
->xexpose
.x
, evp
->xexpose
.y
,
401 evp
->xexpose
.width
, evp
->xexpose
.height
,
416 topgc
= up
? hilite
[set
] : shadow
[set
];
417 bottomgc
= up
? shadow
[set
] : hilite
[set
];
420 if (Ffont
->font
!= NULL
)
423 gcv
.font
= Ffont
->font
->fid
;
424 XChangeGC(dpy
, graph
[set
], gcm
, &gcv
);
427 Fontheight
=FButtonFont
->height
;
429 if ((FftSupport
&& Ffont
->fftf
.fftfont
!= NULL
) ||
430 (button
->p
.picture
!= 0 && button
->p
.alpha
!= 0) ||
431 (colorset
[set
] >= 0 &&
432 Colorset
[colorset
[set
]].icon_alpha_percent
< 100))
437 /* handle transparency by clearing button, otherwise paint with
441 if (CSET_IS_TRANSPARENT_PR_PURE(colorset
[set
]))
444 dpy
, win
, rect
.x
, rect
.y
, rect
.width
,
447 else if (CSET_IS_TRANSPARENT_PR_TINT(colorset
[set
]))
449 SetRectangleBackground(
450 dpy
, win
, rect
.x
, rect
.y
, rect
.width
,
451 rect
.height
, &Colorset
[colorset
[set
]], Pdepth
,
457 dpy
, win
, background
[set
],
458 rect
.x
, rect
.y
, rect
.width
, rect
.height
);
462 if (button
->p
.picture
!= 0)
464 /* clip pixmap to fit inside button */
465 int height
= min(button
->p
.height
, h
);
466 int offset
= (button
->p
.height
> h
) ?
467 0 : ((h
- button
->p
.height
) >> 1);
469 fra
.mask
= FRAM_DEST_IS_A_WINDOW
;
470 if (colorset
[set
] >= 0)
472 fra
.mask
|= FRAM_HAVE_ICON_CSET
;
473 fra
.colorset
= &Colorset
[colorset
[set
]];
475 if (frect_get_intersection(
476 rect
.x
, rect
.y
, rect
.width
, rect
.height
,
477 x
+ 2 + button
->reliefwidth
, y
+offset
,
478 button
->p
.width
, height
, &inter
))
480 PGraphicsRenderPicture(
481 dpy
, win
, &(button
->p
), &fra
,
482 win
, graph
[set
], None
, None
,
483 inter
.x
- (x
+ 2 + button
->reliefwidth
),
484 inter
.y
- (y
+offset
),
485 inter
.width
, inter
.height
,
486 inter
.x
, inter
.y
, inter
.width
, inter
.height
,
489 newx
= button
->p
.width
+2*INNER_MARGIN
;
496 if (!button
->is_iconified
)
498 static int icon_offset
= -1;
500 if (icon_offset
== -1)
501 icon_offset
= FlocaleTextWidth(
502 FButtonFont
, "(", 1);
509 (w
- button
->tw
) / 2 - button
->reliefwidth
,
513 /* check if the string needs to be truncated */
514 string
= button
->title
;
515 len
= strlen(string
);
517 if (newx
+ button
->tw
+ 2 * button
->reliefwidth
+ INNER_MARGIN
> w
)
519 if (button
-> truncatewidth
== w
)
521 /* truncated version already calculated use it */
522 string
= button
->truncate_title
;
523 len
= strlen(string
);
529 /* move the ptr up until the rest fits */
531 (newx
+ FlocaleTextWidth(
534 + 2 * button
->reliefwidth
+
540 button
->truncatewidth
= w
;
541 button
->truncate_title
= string
;
546 (newx
+ FlocaleTextWidth(
547 FButtonFont
, string
, len
)
548 + 2 * button
->reliefwidth
+
556 FwinString
->str
= string
;
557 FwinString
->len
= len
;
558 FwinString
->x
= x
+newx
+button
->reliefwidth
;
559 FwinString
->y
= y
+1+button
->reliefwidth
+FButtonFont
->ascent
;
560 FwinString
->gc
= graph
[set
];
561 t_region
= XCreateRegion();
562 XUnionRectWithRegion (&rect
, t_region
, t_region
);
563 FwinString
->flags
.has_clip_region
= True
;
564 FwinString
->clip_region
= t_region
;
565 FwinString
->flags
.has_colorset
= False
;
566 if (colorset
[set
] >= 0)
568 FwinString
->colorset
= &Colorset
[colorset
[set
]] ;
569 FwinString
->flags
.has_colorset
= True
;
571 FlocaleDrawString(dpy
, FButtonFont
, FwinString
, FWS_HAVE_LENGTH
);
572 FwinString
->flags
.has_clip_region
= False
;
573 XDestroyRegion(t_region
);
575 /* Draw relief last */
577 dpy
,win
,x
,y
,w
-1,h
-1,topgc
,bottomgc
,button
->reliefwidth
);
579 button
->needsupdate
=0;
583 DrawButtonArray - Draw the whole array (all=1), or only those that need.
585 void DrawButtonArray(
586 ButtonArray
*barray
, Bool all
, Bool clear_bg
, XEvent
*evp
)
589 int i
= 0; /* buttons displayed */
591 for(btn
= barray
->head
; btn
!= NULL
; btn
= btn
->next
)
592 if (IsButtonVisible(btn
))
594 if (all
|| btn
->needsupdate
)
595 DoButton(btn
, barray
->x
, barray
->y
+ (i
* (barray
->h
+ 1)),
596 barray
->w
, barray
->h
, clear_bg
, evp
);
602 Mark all the buttons in the array as dirty
604 void DirtyButtonArray(ButtonArray
*barray
)
608 for (btn
= barray
->head
; btn
!= NULL
; btn
= btn
->next
)
610 btn
->needsupdate
= 1;
617 DrawButtonArray - Draw the whole array (all=1), or only those that need.
619 void DrawTransparentButtonArray(ButtonArray
*barray
)
622 int i
= 0; /* buttons displayed */
624 for (i
= 0; i
!= MAX_COLOUR_SETS
; i
++)
626 int cset
= colorset
[i
];
628 if (!CSET_IS_TRANSPARENT_ROOT(cset
))
633 XFreePixmap(dpy
, pixmap
[i
]);
634 pixmap
[i
] = CreateBackgroundPixmap(
635 dpy
, win
, win_width
, win_height
,
636 &Colorset
[cset
], Pdepth
,
637 background
[i
], False
);
638 XSetTile(dpy
, background
[i
], pixmap
[i
]);
642 for(btn
= barray
->head
; btn
!= NULL
; btn
= btn
->next
)
644 if (IsButtonVisible(btn
))
646 if (CSET_IS_TRANSPARENT(colorset
[btn
->set
]))
650 barray
->y
+ (i
* (barray
->h
+ 1)),
651 barray
->w
, barray
->h
, True
, NULL
);
658 SwitchButton - Alternate the state of a button
660 void SwitchButton(ButtonArray
*array
, int butnum
)
664 btn
= find_n(array
, butnum
);
669 DrawButtonArray(array
, False
, True
, NULL
);
673 /* -------------------------------------------------------------------------
674 RadioButton - Enable button i and verify all others are disabled
675 ------------------------------------------------------------------------- */
676 void RadioButton(ButtonArray
*array
, int butnum
, int butnumpressed
)
681 for(temp
=array
->head
,i
=0; temp
!=NULL
; temp
=temp
->next
,i
++)
685 if (ShowFocus
&& temp
->up
)
690 if (!(temp
->set
& 2))
696 else if (i
== butnumpressed
)
701 temp
->needsupdate
= 1;
706 if (ShowFocus
&& !temp
->up
)
709 temp
->needsupdate
= 1;
714 temp
->needsupdate
= 1;
721 WhichButton - Based on x,y which button was pressed
723 int WhichButton(ButtonArray
*array
,int x
, int y
)
730 if (x
<array
->x
|| x
>array
->x
+array
->w
|| num
<0 || num
>array
->count
-1) num
=-1;
733 for(i
=0, n
= 0;n
< (num
+ 1) && temp
!= NULL
;temp
=temp
->next
, i
++)
735 if (IsButtonVisible(temp
))
744 ButtonName - Return the name of the button
746 char *ButtonName(ButtonArray
*array
, int butnum
)
750 temp
=find_n(array
,butnum
);
755 PrintButtons - Print the array of button names to the console. (Debugging)
757 void PrintButtons(ButtonArray
*array
)
761 ConsoleMessage("List of Buttons:\n");
762 for(temp
=array
->head
;temp
!=NULL
;temp
=temp
->next
)
763 ConsoleMessage(" %s is %s\n",temp
->title
,(temp
->up
) ? "Up":"Down");
767 ButtonPicture - Return the mini icon associated with the button
769 FvwmPicture
*ButtonPicture(ButtonArray
*array
, int butnum
)
773 if (!FMiniIconsSupported
)
777 temp
=find_n(array
,butnum
);
782 IsButtonVisible - Says if the button should be in winlist
784 int IsButtonVisible(Button
*btn
)
787 if ((!ShowCurrentDesk
|| btn
->desk
== CurrentDesk
|| btn
->is_sticky
) &&
788 (!btn
->skip
|| !UseSkipList
))
795 IsButtonIndexVisible - Says if the button of index butnum should be
798 int IsButtonIndexVisible(ButtonArray
*array
, int butnum
)
802 temp
=find_n(array
,butnum
);
803 if (temp
== NULL
) return 0;
804 if (IsButtonVisible(temp
))
812 ButtonArrayMaxWidth - Calculate the width needed for the widest title
814 int ButtonArrayMaxWidth(ButtonArray
*array
)
818 for(temp
=array
->head
;temp
!=NULL
;temp
=temp
->next
)